我正在使用反射和表达式树的组合,并希望将某些属性访问器从类传回调用方法。我当前的代码有一个遍历类并返回MemberExpression
s 列表的方法。然后调用者遍历成员表达式并创建 lambda,然后应该使用被检查类的实例调用它以返回属性的值。
以下是没有方法调用的示例(LINQPad 中的 Runnable):
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:从范围“”引用的“UserQuery+Test”类型的变量“baseType”,但未定义
但是,如果我将 lambda 的创建更改为:
var lambda = Expression.Lambda<Func<Test, string>>(memberAccess, baseType);
也就是说,将 替换为Expression.Parameter
之前使用的变量,然后它就可以工作了。在我想使用它的情况下,这不是(很容易)可能的,因为我必须将原始参数与列表一起返回(当然,我可以返回一个元组,但我不希望这样做,如果它是没有必要)。
为什么它会这样工作?检查DebugView
lambda,无论使用什么方法,它们都是完全相同的:
.Lambda #Lambda1<System.Func`2[UserQuery+Test,System.String]>(UserQuery+Test $baseType)
{
$baseType.S
}