给定以下类集:
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
方法内部,如何获得对classToPass
传入的实例的引用ProcessObject
?
编辑:评论强调了试图解析表达式树的复杂性,表达式树的组成可能有很大差异。
但是,在这种特殊情况下,有两个事实大大减少了这种变化:
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
本文收集自互联网,转载请注明来源。
如有侵权,请联系[email protected] 删除。
我来说两句