我有这个lambda表达式Expression<Func<bool>> commandToExecute
然后我用一个方法传递一个类的实例:
_commandExecuter.ProcessCommand (() => aClass.Method())
如何在aClass
方法中获取ProcessCommand
的实例?
我想执行此类的一些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<bool>> commandToExecute
var referredProviderInstance = GetReferredProviderInstance(body);
这里的问题是,ConstantExpression的强制转换为Null
。所以constantExpression
始终为空。
有什么想法吗?
编辑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;
}
但是这里出现了一个新问题。我只获得了我的提供者的参考实例所在的窗体实例。
如何获取lambda表达式的真实对象(aClass
)?
答案 0 :(得分:12)
这实际上是可行的,但这取决于您传递给此方法的内容。假设您有一个场景,您将所在类的实例方法传递给ProcessCommand
:
public class TestClass
{
public void TestMethod()
{
ProcessCommand(() => MethodToCall());
}
public bool MethodToCall() { return true; }
void ProcessCommand(Expression<Func<bool>> expression) { ... }
}
然后您可以使用以下ProcessCommand
方法。这只能起作用,因为在此实例上调用了MethodToCall
。
void ProcessCommand(Expression<Func<bool>> 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<Func<bool>> expression) { ... }
}
public class CalledClass
{
public bool MethodToCall() { return true; }
}
我们调用的方法现在位于另一个类中,并且不会在此实例上调用,而是在名为CalledClass
的{{1}}实例上调用。但是编译器如何将calledClass
变量传递给lambda表达式?没有任何内容可以定义字段calledClass
,可以调用方法calledClass
。
编译器通过生成一个名为MethodToCall
的字段的内部类来解决此问题。因此,calledClass
方法现在变为:
ProcessCommand
稍微复杂一点,因为编译器必须生成匿名内部类。
答案 1 :(得分:2)
“开箱即用”是不可能的,你可以用反射破解某些东西,但是这是不可取的,它会非常倒退。
编辑:根据罗纳德的说法,实际上是可能的,但仍然相当倒退。这样的隐藏副作用使代码难以阅读和维护。
相反,您的ProcessCommand应该使用整个aClass
对象,或者更优选地使用IMyCommand
.Method()
接口以及ProcessCommand
所需的其他方法和属性。然后,aClass.GetType()
类型应实现IMyCommand
。