c# - 表达式树参数是否需要重用相同的实例?

标签 c# expression-trees

我正在使用反射树和表达式树的组合,并希望将某些属性访问器从类传回调用方法。我当前的代码有一个遍历类并返回 MemberExpression 列表的方法。然后,调用者遍历成员表达式并创建 lambda,然后应使用被检查类的实例调用它以返回属性的值。

这是一个没有方法调用的示例(在 LINQPad 中可运行):

void Main()
{
    var t = new Test { Prop = "Test" };

    var property = t.GetType().GetProperty("Prop");

    var baseType = Expression.Parameter(typeof(Test), "baseType");
    var memberAccess = Expression.MakeMemberAccess(baseType, property);
    var lambda = Expression.Lambda<Func<Test, string>>(memberAccess, Expression.Parameter(typeof(Test), "baseType"));
    var func = lambda.Compile();
    var result = func(t);
    result.Dump();
}

class Test {
    public string Prop { get; set; }
}

这不起作用,抛出这个异常:

InvalidOperationException: variable 'baseType' of type 'UserQuery+Test' referenced from scope '', but it is not defined

但是,如果我将 lambda 的创建更改为:

var lambda = Expression.Lambda<Func<Test, string>>(memberAccess, baseType);

也就是说,将 Expression.Parameter 替换为之前使用的变量,然后就可以了。这在我想使用它的场景中(很容易)是不可能的,因为我必须将原始参数与列表一起返回(当然,我可以返回一个元组,但我宁愿不这样做,如果它是不必要)。

为什么会这样?查看 lambda 的 DebugView,无论使用什么方法,它们都是完全一样的:

.Lambda #Lambda1<System.Func`2[UserQuery+Test,System.String]>(UserQuery+Test $baseType)
{
    $baseType.S
}

最佳答案

是的,你需要引用之前使用的ParameterExpression。这也不会编译:

private String Foo(Test myParam)
{
  return myAnotherParam.MyProperty;
}

通过在 lambda 中实例化新的 ParameterExpression,您正在做同样的事情(但请注意,在制作 lambda 时,您是以相反的顺序进行的 - 首先,您正在构建一个方法体, 然后 - 一个方法声明):

// return myAnotherParam.MyProperty;
var baseType = Expression.Parameter(typeof(Test), "baseType");
var memberAccess = Expression.MakeMemberAccess(baseType, property);

// private String Foo(MyClass myParam)
var lambda = Expression.Lambda<Func<Test, string>>(memberAccess, Expression.Parameter(typeof(Test), "baseType"));

关于c# - 表达式树参数是否需要重用相同的实例?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12043390/

相关文章:

c# - 从 dll 调用 C 函数后 C# 代码中的 ArithmeticException

C# 列表属性初始化模式

c# - 如何使用表达式将 classProperty 传递给 LINQ

c# - 奇怪的异常编译动态构建表达式

c# - Entity Framework 6 - 将主键作为类型的属性

c# - 泛型与对象性能

.net - "this"的启发式和闭包好吗? (表达式树)

c# - LINQ 表达式帮助 Func TEntity、TType

c# - 为什么要使用 Expression<Func<T>> 而不是 Func<T>?

c# - 如果在 'await' 之后抛出,则从任务中抛出的异常被吞没