如何使用反射在C# 7.0中获取不包括本地函数的方法?

4

有没有一种方法可以使用反射获取类中的私有静态方法,而不获取这些方法内定义的任何本地函数?

例如,我有一个如下所示的类:

public class Foo {
    private static void FooMethod(){
        void LocalFoo(){
           // do local stuff
        }
        // do foo stuff
    }
}

如果我使用反射来获取私有静态方法,代码如下:
var methods = typeof(Foo).GetMethods(BindingFlags.Static|BindingFlags.NonPublic)
    .Select(m=>m.Name).ToList();

然后我得到了这样的结果:
FooMethod
<FooMethod>g__LocalFoo5_0

包括本地函数生成的复杂编译器名称。

到目前为止,我能想到的最好方法是添加一个Where子句来过滤掉本地函数,例如:

    var methods = typeof(Foo).GetMethods(BindingFlags.Static|BindingFlags.NonPublic)
        .Where(m=>!m.Name.Contains("<")
        .Select(m=>m.Name).ToList();

或者:

    var methods = typeof(Foo).GetMethods(BindingFlags.Static|BindingFlags.NonPublic)
        .Where(m=>!m.Name.Contains("__")
        .Select(m=>m.Name).ToList();

它返回的是正确的,过滤也是必须做的,同时也是许多情况下使用LINQ查询来过滤所需成员的首选和标准方式(我们不使用BindingFlags)。 - King King
5
有不止一种方法来做这件事。奇怪的名称是其中一种方法,但那只是实现细节。一个理想的方法是过滤掉由编译器生成而不是用户代码生成的任何方法。使用MethodInfo.GetCustomAttributes(),并过滤掉具有[System.Runtime.CompilerServices.CompilerGeneratedAttribute]的属性。 - Hans Passant
1个回答

1
什么意思?
var methods = typeof(Foo).GetMethods(BindingFlags.Static | BindingFlags.NonPublic)
    .Where(x => !x.IsAssembly)
    .Select(x => x.Name)
    .ToList();

结果:

"FooMethod"

IsAssembly 属性摘要:

获取一个值,该值指示此方法或构造函数的潜在可见性是否由 System.Reflection.MethodAttributes.Assembly 描述;也就是说,该方法或构造函数最多对同一程序集中的其他类型可见,并且不对程序集外的派生类型可见。


这假设所有本地函数都是“internal”,这并不正确 - svick
它可以是“私有的”,在这种情况下,“IsAssembly”将返回“false”。 - svick
这就是为什么它是 *!*x.Assembly。OP想要过滤掉 private static 函数内部的本地函数。 - ceferrari
不,它不会。感谢您在不了解情况的情况下给出负评。请再次阅读属性摘要:“该方法或构造函数最多只对同一程序集中的其他类型可见”,因此需要使用否定运算符。下次请提供一个能够失败的工作示例,而不是基于猜测的无用SharpLab代码。 - ceferrari
不错的尝试,但这并不满足OP使用反射获取类中私有静态方法的要求。1-您的“FooMethod()”方法不是静态的。2-您故意更改了“BindingFlags”(包括“BindingFlags.Instance”),以适应您自己的需求,而不是OP的需求,从而操纵结果。3-成熟点。 - ceferrari
显示剩余2条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接