【问题标题】:Use Reflection to get methods excluding local functions in C# 7.0?在 C# 7.0 中使用反射获取不包括本地函数的方法?
【发布时间】:2017-11-16 03:43:31
【问题描述】:

有没有办法使用反射来获取类中的私有静态方法,而无需在这些方法中定义任何本地函数?

例如,我有一个这样的类:

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

【问题讨论】:

  • 它返回的是正确的,过滤也是必须做的以及首选和标准的方式(在许多情况下我们不使用BindingFlags,只是去LINQ查询来过滤所需的成员)。
  • 有不止一种方法可以做到这一点。古怪的名字是一种方式,但这是一个实现细节。当然,一种理想的方法是过滤掉由编译器生成的任何方法,而不是用户代码。使用 MethodInfo.GetCustomAttributes() 并过滤掉那些具有 [System.Runtime.CompilerServices.CompilerGeneratedAttribute]

标签: c# reflection c#-7.0


【解决方案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 描述;也就是方法 或构造函数最多对同一程序集中的其他类型可见,并且是 对程序集外的派生类型不可见。

【讨论】:

  • 这里假设所有的本地函数都是internalwhich is not true
  • 您的示例中生成的类签名是internal class Foointernal class 中的函数怎么可能不是内部函数?
  • 可以是private,在这种情况下IsAssembly会返回false
  • 这就是为什么它是*!*x.Assembly。 OP 想要过滤本地函数 inside private static 函数。
  • 对于这样的本地函数,x.IsAssembly 将是 false,因此 !x.IsAssembly 将是 true,因此它将包含在结果中。
猜你喜欢
  • 2020-04-26
  • 1970-01-01
  • 2017-09-15
  • 2017-04-18
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多