使用反射列出(检测)方法中的闭包

时间:2014-12-19 16:59:55

标签: c# reflection closures

我知道我可以使用MethodInfo.GetMethodBody()在方法中迭代所有本地定义的变量.LocalVariables。

但是如果我将方法定义为:

public static void somemethod( int someint )
{
    int test = 1;

    HM.M(() =>
    {
        test = 2;
    });
}

匿名方法可以访问someint并测试为闭包,但GetMethodBody()。LocalVariables将为空。

有没有办法使用反射来检测闭包?

1 个答案:

答案 0 :(得分:1)

好吧,我找到了答案。编译器使用编译器生成的类实现c#中的闭包。编译器生成一个类,在该类中复制将在方法中可访问的所有变量,并且方法本身封装在此类中。外部变量值将复制到类中。

因此,在上面的示例中,M方法具有签名:

public void M( Action method )

获取闭包列表的步骤是:

MethodInfo mi = method.Method; 

FieldInfo[] fields = mi.DeclaringType.GetFields
                                    (
                                        BindingFlags.NonPublic |
                                        BindingFlags.Instance |
                                        BindingFlags.Public |
                                        BindingFlags.Static
                                    );

DeclaringType将是用于实现闭包的编译器生成的类。

在fields数组中,将列出所有闭包。

获取闭包的VALUES是另一回事,但它不是这个问题的一部分。

编辑: 正如@leppie所指出的,获取值很简单:

object res = fields[ 0 ].GetValue( method.Target );