Roo*_*ian 11 c# lambda delegates
我有这个lambda表达式 Expression<Func<bool>> commandToExecute
然后我用一个方法传递一个类的实例:
_commandExecuter.ProcessCommand (() => aClass.Method())
Run Code Online (Sandbox Code Playgroud)
我如何获得实例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;
}
Run Code Online (Sandbox Code Playgroud)
方法调用看起来像这样......
Expression body = commandToExecute.Body; // this is the method parameter Expression<Func<bool>> commandToExecute
var referredProviderInstance = GetReferredProviderInstance(body);
Run Code Online (Sandbox Code Playgroud)
这里的问题是,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;
}
Run Code Online (Sandbox Code Playgroud)
但是这里出现了一个新问题.我只获得了我的提供者的参考实例所在的Windows窗体的实例.
我如何获得lambda表达式的真实对象(aClass)?
Ron*_*erg 12
这实际上是可能的,但这取决于您传递给此方法的内容.假设您有一个场景,您传递您所在的类的实例方法ProcessCommand:
public class TestClass
{
public void TestMethod()
{
ProcessCommand(() => MethodToCall());
}
public bool MethodToCall() { return true; }
void ProcessCommand(Expression<Func<bool>> expression) { ... }
}
Run Code Online (Sandbox Code Playgroud)
然后您可以使用以下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;
}
Run Code Online (Sandbox Code Playgroud)
更复杂的情况如下:
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; }
}
Run Code Online (Sandbox Code Playgroud)
我们调用的方法现在在另一个类中,并且不在此实例上调用,而是在CalledClass被调用的实例上调用calledClass.但是编译器如何将calledClass变量传递给lambda表达式?没有任何东西可以定义可以调用calledClass该方法的字段MethodToCall.
编译器通过生成一个带有名称的一个字段的内部类来解决这个问题calledClass.结果这个ProcessCommand方法现在变成了这个:
public void ProcessCommand(Expression<Func<bool>> 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);
}
Run Code Online (Sandbox Code Playgroud)
稍微复杂一点,因为编译器必须生成匿名内部类.