在.NET类中获取枚举类型

5

Consider the following C# class declaration:

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

这段代码坐落在一个单独的类库/DLL中。

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

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

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

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


而且,一旦我有了枚举的System.Type,我就知道如何查询值。获取枚举本身的信息才是棘手的部分。 - Rob Nicholson
4
GetNestedType :获取嵌套在当前 Type 中指定名称的类型。 - user4003407
糟糕!那可能就是它了...以后再说! - Rob Nicholson
1
这就是应该使用接口的地方。 - DPac
3个回答

11

只需要这样做:

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

测试res != null以查看是否存在此类型。

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

附加说明:如果嵌套类型偶尔是公共嵌套的,请改用BindingFlags.NonPublic | BindingFlags.Public


谢谢 - 这正是我需要的。我浏览了 System.Type 中的方法,我的眼睛可能已经变得模糊了。显然真的很明显。 - Rob Nicholson
是的,最好检查公共枚举。 - Rob Nicholson

2
我想到了以下两种方法:
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;
    }
}

-1
var types = typeof(MyClass).Assembly.DefinedTypes;

foreach (var type in types)
{
    Console.WriteLine(type.Name);
}

输出:

MyClass
颜色


1
这将在定义“MyClass”的整个程序集中触发搜索。我怀疑这不是预期的解决方案 - “有没有办法在运行时检查类是否包含名为Colours的枚举?” - Binkan Salaryman

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