如何使用MethodInfo调用非静态的lambda方法(使用<>c__DisplayClass1)

本文关键字:使用 DisplayClass1 方法 调用 MethodInfo 何使用 静态 lambda | 更新日期: 2023-09-27 18:01:25

考虑以下代码:

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:

非静态方法需要目标。

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

我的问题是,我怎样才能使它工作?我明白,因为lambda2Method是非静态的,我需要为MethodBase.Invoke()object obj参数提供一个值,它需要是<>c__DisplayClass1的一个实例,但是我如何获得这个实例?

如何使用MethodInfo调用非静态的lambda方法(使用<>c__DisplayClass1)

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

所以,如果你真的必须使用MethodInfo,那么你可以通过使用反射来创建所需的实例:

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 });