考虑以下代码:

bool result;

Func<int, bool> lambda1 = i => i == 9000;
MethodInfo lambda1Method = lambda1.Method;
result = (bool)lambda1Method.Invoke(null, new object[] { 9000 }); // this works, result = true

int myLocalVariable = 9000;
Func<int, bool> lambda2 = i => i == myLocalVariable;
MethodInfo lambda2Method = lambda2.Method;
result = (bool)lambda2Method.Invoke(null, new object[] { 9000 }); // error


调用lambda2Method会导致System.Reflection.TargetException


  非静态方法需要目标。


这个问题here解释了为什么lambda1Method是静态的而lambda2Method是非静态的。基本上,如果lambda包含局部变量,则会动态创建一个类,该类将每个局部变量解释为一个字段。 lambda2Method成为该新类的实例方法。我知道这是因为lambda2Method.DeclaringType<>c__DisplayClass1,而lambda2Method.IsStaticfalse

我的问题是,我该如何进行这项工作?我知道,因为lambda2Method是非静态的,所以我需要为object objMethodBase.Invoke()参数提供一个值,并且它必须是<>c__DisplayClass1的实例,但是如何获取该实例?

最佳答案

您需要解决的主要问题是如何创建由编译器生成的类型的实例?

因此,如果确实需要使用MethodInfo,则可以使用Reflection创建所需的实例:

var instance = Activator.CreateInstance(lambda2Method.DeclaringType);

result = lambda2Method.Invoke(instance, new object[] { 9000 });


摘要:

方法lambda2的声明类型是由编译器生成的隐藏类。 MethodInfo.Invoke需要该类型的目标实例才能调用非静态方法。

编辑:

要正确获取myVariable的捕获值,可以使用Target属性:

result = lambda2Method.Invoke(lambda2.Target, new object[] { 9000 });

08-28 04:08