给定以下一组类:
public class MyClass
{
public int MyInt { get; set; }
}
public class ObjectProcessor
{
public int ProcessObject(MyClass myClass)
{
return myClass.MyInt ++;
}
}
public class Runner
{
public void Run()
{
var classToPass = new MyClass();
FuncExecutor.ExecuteAction<MyClass>(x => x.ProcessObject(classToPass));
}
}
public static class FuncExecutor
{
public static void ExecuteAction<T>(Expression<Func<ObjectProcessor, int>> expression)
{
// var func = expression.Compile(); ... does having an Expression help?
// How can I get a reference to 'classToPass' at this point?
// The 'classToPass' Type is known to be 'T', in this case 'MyClass'.
}
}
在 ExecuteAction
方法中,如何获取对传递给 ProcessObject
的 classToPass
实例的引用?
编辑:评论强调了尝试解析表达式树的复杂性,表达式树的组成可能差异很大。
但是,在这种特殊情况下,有两个事实可以大大减少这种变化:
ProcessObject
只会接受一个参数。- 参数类型是预先知道的。
更改代码以表达这一点。
最佳答案
非常具体地回答:
public class Runner
{
public void Run()
{
var classToPass = new MyClass();
classToPass.MyInt = 42;
FuncExecutor.ExecuteAction(x => x.ProcessObject(classToPass));
}
}
public class FuncExecutor
{
public static void ExecuteAction(Expression<Func<ObjectProcessor, int>> expression)
{
var lambdaExpression = (LambdaExpression)expression;
var methodCallExpression = (MethodCallExpression)lambdaExpression.Body;
var memberExpression = (MemberExpression)methodCallExpression.Arguments[0];
var constantExpression = (ConstantExpression)memberExpression.Expression;
var fieldInfo = (FieldInfo)memberExpression.Member;
var myClassReference = (MyClass) fieldInfo.GetValue(constantExpression.Value);
Console.WriteLine(myClassReference.MyInt); // prints "42"
}
}
请注意,当您将 lambda 传递给 ExecuteAction
方法时,您会捕获一个局部变量引用 (classToPass
)。编译器将生成一些代码来正确处理它。更准确地说,它将生成一个具有类型 MyClass
的单个成员(字段)的类型,以保存引用并从此点使用它。这就是为什么您会在参数表达式列表中得到一个 MemberExpression
。
由于不能直接操作这个生成的类型,所以不能只使用成员表达式 Value
属性。但是您可以使用 MemberInfo
和目标引用(编译器生成类型的实例)动态调用成员访问器。
我不会依赖此代码。
您可以在此处阅读有关 lambda 相关编译器生成代码的更多信息,例如:http://thewalkingdev.blogspot.fr/2012/04/c-lambda-expressions-and-closures.html
关于c# - 获取对作为函数传递的 Lambda 中的参数的引用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21579900/