【问题标题】:Get type of enum in .NET class获取 .NET 类中的枚举类型
【发布时间】:2015-12-20 22:58:46
【问题描述】:

考虑以下 C# 类声明:

public class MyClass {
    private enum Colours { Red, Green, Blue }
}

位于单独的类库/DLL 中。

仅给定 typeof(MyClass) 对象 (System.Type),有没有办法在运行时检查该类是否包含一个名为 Colors 的枚举,如果是,则返回它对应的 System.Type 对象?

我要做的是编写一些给定类类型的通用代码,并确定其中是否包含一个特别命名的枚举,然后查询枚举中的值。

我知道如何使用反射来查询 GetFields、GetProperties 等内容,但 System.Type 中没有 GetClasses 或 GetEnums 方法。

我怀疑这种信息在程序集中?

【问题讨论】:

  • 而且,一旦我有了枚举的 System.Type,我就知道如何查询这些值。它正在获取有关枚举本身的信息,这是一个棘手的问题
  • 噢!可能就是这样......以后!
  • 这是应该使用接口的地方。

标签: c# .net class reflection enums


【解决方案1】:

我想出了以下两种方法:

public class MyClass {
    private enum Colours { Red, Green, Blue }

    private class Inner {
        private enum Colours { Black, White }
    }
}

class Program {
    static void Main(string[] args) {
        Type coloursType;
        // 1. enumerator
        coloursType = typeof(MyClass).EnumerateNestedTypes()
            .Where(t => t.Name == "Colours" && t.IsEnum)
            .FirstOrDefault();
        // 2. search method
        coloursType = typeof(MyClass).FindNestedType(t => t.Name == "Colours" && t.IsEnum);

        if(coloursType != null) {
            Console.WriteLine(string.Join(", ", coloursType.GetEnumNames()));
        } else {
            Console.WriteLine("Type not found");
        }
        Console.ReadKey();
    }
}

public static class Extensions {
  public static IEnumerable<Type> EnumerateNestedTypes(this Type type) {
        const BindingFlags flags = BindingFlags.DeclaredOnly | BindingFlags.Public | BindingFlags.NonPublic;
        Queue<Type> toBeVisited = new Queue<Type>();
        toBeVisited.Enqueue(type);
        do {
            Type[] nestedTypes = toBeVisited.Dequeue().GetNestedTypes(flags);
            for(int i = 0, l = nestedTypes.Length; i < l; i++) {
                Type t = nestedTypes[i];
                yield return t;
                toBeVisited.Enqueue(t);
            }
        } while(toBeVisited.Count != 0);
    }

    public static Type FindNestedType(this Type type, Predicate<Type> filter) {
        const BindingFlags flags = BindingFlags.DeclaredOnly | BindingFlags.Public | BindingFlags.NonPublic;
        Type[] nestedTypes = type.GetNestedTypes(flags);
        foreach(var nestedType in nestedTypes) {
            if(filter(nestedType)) {
                return nestedType;
            }
        }
        foreach(var nestedType in nestedTypes) {
            Type result = FindNestedType(nestedType, filter);
            if(result != null) {
                return result;
            }
        }
        return null;
    }
}

【讨论】:

    【解决方案2】:

    只要做:

    var res = typeof(MyClass).GetNestedType("Colours", BindingFlags.NonPublic);
    

    测试res != null 看看是否存在这种类型。

    然后测试res.IsEnum看嵌套类型是否为枚举。

    补充:如果嵌套类型偶尔嵌套public,请改用BindingFlags.NonPublic | BindingFlags.Public

    【讨论】:

    • 谢谢 - 那只是票。我浏览了 System.Type 中的方法,我的眼睛一定对此感到茫然。真的很明显
    • 是的,可能最好检查公共枚举
    【解决方案3】:
    var types = typeof(MyClass).Assembly.DefinedTypes;
    
    foreach (var type in types)
    {
        Console.WriteLine(type.Name);
    }
    

    输出:

    我的班级
    颜色

    【讨论】:

    • 这将触发在定义MyClass 的整个程序集中进行搜索。我怀疑这是预期的解决方案-“有什么方法可以检查该类在运行时是否包含名为 Colors 的枚举”
    猜你喜欢
    • 2017-01-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多