如何从lambda表达式获取引用实例的实例

我有这个lambda表达式Expression<Func> commandToExecute

然后我用一个方法传递一个类的实例:

 _commandExecuter.ProcessCommand (() => aClass.Method()) 

如何在ProcessCommand方法中获取aClass的实例?

我想执行此类的一些addiontal方法或获取一些属性值。

这可能吗?

编辑:我现在已经编写了一个简单的静态助手方法来获取实例:

 private static object GetReferredProviderInstance(Expression body) { var methodCallExpression = body as MethodCallExpression; if (methodCallExpression != null) { var constantExpression = methodCallExpression.Object as ConstantExpression; if (constantExpression != null) return constantExpression.Value; } return null; } 

方法调用看起来像这样……

 Expression body = commandToExecute.Body; // this is the method parameter Expression<Func> commandToExecute var referredProviderInstance = GetReferredProviderInstance(body); 

这里的问题是,ConstantExpression的强制转换为Null 。 因此, constantExpression始终为null。

有任何想法吗?

编辑2我修复了问题…

 private static object GetReferredProviderInstance(Expression body) { var methodCallExpression = body as MethodCallExpression; if (methodCallExpression != null) { var memberExpression = methodCallExpression.Object as MemberExpression; if (memberExpression != null) { var constantExpression = memberExpression.Expression as ConstantExpression; if (constantExpression != null) return constantExpression.Value; } } return null; } 

但是这里出现了一个新问题。 我只获得了我的提供者的参考实例所在的Windows窗体的实例。

我如何获得lambda表达式的真实对象aClass )?

这实际上是可能的,但这取决于您传递给此方法的内容。 假设您有一个场景,您将所在类的实例方法传递给ProcessCommand

 public class TestClass { public void TestMethod() { ProcessCommand(() => MethodToCall()); } public bool MethodToCall() { return true; } void ProcessCommand(Expression> expression) { ... } } 

然后,您可以使用以下ProcessCommand方法。 这只能起作用,因为在此实例上调用了MethodToCall

 void ProcessCommand(Expression> expression) { var lambda = (LambdaExpression) expression; var methodCall = (MethodCallExpression) lambda.Body; var constant = (ConstantExpression) methodCall.Object; var myObject = constant.Value; } 

更复杂的情况如下:

 public class CallingClass { public void TestMethod() { var calledClass = new CalledClass(); ProcessCommand(() => calledClass.MethodToCall()); } void ProcessCommand(Expression> expression) { ... } } public class CalledClass { public bool MethodToCall() { return true; } } 

我们调用的方法现在在另一个类中,并且不在此实例上调用,而是在名为calledClass实例上调用。 但是编译器如何将calledClass变量传递给lambda表达式? 没有什么可以定义一个calledClass的字段,可以调用calledClass方法。

编译器通过生成一个名为calledClass字段的内部类来解决这个calledClass 。 结果, ProcessCommand方法现在成为:

 public void ProcessCommand(Expression> expression) { // The expression is a lambda expression with a method call body. var lambda = (LambdaExpression) expression; var methodCall = (MethodCallExpression) lambda.Body; // The method is called on a member of some instance. var member = (MemberExpression) methodCall.Object; // The member expression contains an instance of the anonymous class that // defines the member... var constant = (ConstantExpression) member.Expression; var anonymousClassInstance = constant.Value; // ...and the member itself. var calledClassField = (FieldInfo) member.Member; // With an instance of the anonymous class and the field, we can get its value. var calledClass = (CalledClass) calledClassField.GetValue(anonymousClassInstance); } 

稍微复杂一点,因为编译器必须生成一个匿名内部类。

它不可能“开箱即用”,你可以用reflection破解某些东西,但这是不可取的,它将是非常倒退的。
编辑:实际上根据罗纳德可能,但仍然相当倒退。 这样的隐藏副作用使代码难以阅读和维护。

相反,您的ProcessCommand应该使用整个aClass对象,或者更优选的是IMyCommand .Method()IMyCommand接口以及ProcessCommand所需的其他方法和属性。 然后aClass.GetType()类型应该实现IMyCommand