gpt4 book ai didi

c# - Expression.Assign 返回 Func 而不是 Action

转载 作者:行者123 更新时间:2023-11-30 15:25:19 24 4
gpt4 key购买 nike

我正在构建一个基于表达式的小型属性分配器。

这个想法非常简单,只需创建一个获取对象属性并将其分配给另一个对象属性的 Action。

所以如果我处理这个表达式:

public static Action PropertyAssign(object sourceObject, object destObject, 
PropertyInfo sourceProperty, PropertyInfo destProperty)
{
Expression source = Expression.PropertyOrField(
Expression.Constant(sourceObject), sourceProperty.Name);

Expression dest = Expression.PropertyOrField(
Expression.Constant(destObject), destProperty.Name);

Expression assign = Expression.Assign(dest, source);
return (Action)Expression.Lambda(assign).Compile();
}

并尝试调用它,我得到一个异常告诉 Expression.Lambda 是 Func 类型(其中 T 是属性类型)

因为我调用了 assign,所以我希望堆栈上没有剩余值(因此不返回属性本身)。

现在如果我使用 SetMethod 分配属性,例如:

public static Action PropertyAssign(object sourceObject, object destObject, PropertyInfo sourceProperty, PropertyInfo destProperty)
{
Expression source = Expression.PropertyOrField(
Expression.Constant(sourceObject), sourceProperty.Name);
Expression dest = Expression.PropertyOrField(
Expression.Constant(destObject), destProperty.Name);
Expression assign = Expression.Call(
Expression.Constant(destObject), destProperty.SetMethod, source);
Action assigner = (Action)Expression.Lambda(assign).Compile();
return assigner;
}

在这种情况下,Lambda.Compile() 函数会按预期返回一个没有参数/返回值的 Action。

所以这不是一个阻塞问题,但我只是好奇为什么赋值运算符返回一个值以及分配属性(其中 Assign 应该也只是调用 setter 方法)。

还有一种方法可以让第一次调用返回一个 Action 而不是一个函数吗?

最佳答案

您遇到的问题是因为赋值运算符实际上是一个 Func,而 setter 返回一个 void。

通常我实际上会避免使用 Expression.Lambda 正是因为这个问题(以及转换)。

试试这个。

public static Action PropertyAssign(object sourceObject, object destObject, 
PropertyInfo sourceProperty, PropertyInfo destProperty)
{
Expression source = Expression.Property(
Expression.Constant(sourceObject), sourceProperty);

Expression dest = Expression.Property(
Expression.Constant(destObject), destProperty);

Expression assign = Expression.Assign(dest, source);
return Expression.Lambda<Action>(assign).Compile();
}

这不会对您希望 IL 返回的委托(delegate)类型产生任何歧义。

然而,这段特定的代码似乎完全没有意义,因为您无法重用生成的 IL。我建议您缓存它的参数化版本。

public delegate void Assign(TSource sourceObject, TDest destObject);

public static Assign PropertyAssign(TSource sourceObject, TDestdestObject,
PropertyInfo sourceProperty, PropertyInfo destProperty)
{
var sourceObjectExpression = Expression.Parameter(sourceObject);
var destPropertyExpression = Expression.Parameter(destProperty);

Expression source = Expression.Property(
sourceObjectExpression, sourceProperty);

Expression dest = Expression.Property(
destPropertyExpression, destProperty);

Expression assign = Expression.Assign(dest, source);
var lambda = Expression.Lambda<Assign>(
assign, sourceObjectExpression, destPropertyExpression);
return lambda.Compile();
}

关于c# - Expression.Assign 返回 Func 而不是 Action,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31408508/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com