如何通过反射得到一个类型的所有常量?

mas*_*ani 127 .net c# reflection constants

如何使用反射获得任何类型的所有常量?

gdo*_*ica 244

虽然这是一个旧代码:

private FieldInfo[] GetConstants(System.Type type)
{
    ArrayList constants = new ArrayList();

    FieldInfo[] fieldInfos = type.GetFields(
        // Gets all public and static fields

        BindingFlags.Public | BindingFlags.Static | 
        // This tells it to get the fields from all base types as well

        BindingFlags.FlattenHierarchy);

    // Go through the list and only pick out the constants
    foreach(FieldInfo fi in fieldInfos)
        // IsLiteral determines if its value is written at 
        //   compile time and not changeable
        // IsInitOnly determines if the field can be set 
        //   in the body of the constructor
        // for C# a field which is readonly keyword would have both true 
        //   but a const field would have only IsLiteral equal to true
        if(fi.IsLiteral && !fi.IsInitOnly)
            constants.Add(fi);           

    // Return an array of FieldInfos
    return (FieldInfo[])constants.ToArray(typeof(FieldInfo));
}
Run Code Online (Sandbox Code Playgroud)

资源

您可以使用泛型和LINQ轻松将其转换为更干净的代码:

private List<FieldInfo> GetConstants(Type type)
{
    FieldInfo[] fieldInfos = type.GetFields(BindingFlags.Public |
         BindingFlags.Static | BindingFlags.FlattenHierarchy);

    return fieldInfos.Where(fi => fi.IsLiteral && !fi.IsInitOnly).ToList();
}
Run Code Online (Sandbox Code Playgroud)

或者用一行:

type.GetFields(BindingFlags.Public | BindingFlags.Static |
               BindingFlags.FlattenHierarchy)
    .Where(fi => fi.IsLiteral && !fi.IsInitOnly).ToList();
Run Code Online (Sandbox Code Playgroud)

  • 另外,要从FieldInfo获取const的值,请使用GetRawConstantValue(). (46认同)
  • *我+ 1*之前我甚至通过了第二行..我注意到你正在经历每一步......它的设计目的......!当需要从中学习时,这是非常重要的.我希望每个人都有你的经验,就像你在这里一样. (13认同)
  • 我不确定关于IsLiteral和IsInitOnly的断言.在测试时,似乎对于静态只读属性,IsLiteral始终为false - 因此IsLiteral是您需要检查以查找常量的唯一标志,您可以忽略IsInitOnly.我尝试使用不同的字段类型(例如String,Int32)来查看这是否有所不同,但事实并非如此. (4认同)

BCA*_*BCA 42

如果您想从目标类型获取特定类型的所有常量的,这里是一个扩展方法(扩展此页面上的一些答案):

public static class TypeUtilities
{
    public static List<T> GetAllPublicConstantValues<T>(this Type type)
    {
        return type
            .GetFields(BindingFlags.Public | BindingFlags.Static | BindingFlags.FlattenHierarchy)
            .Where(fi => fi.IsLiteral && !fi.IsInitOnly && fi.FieldType == typeof(T))
            .Select(x => (T)x.GetRawConstantValue())
            .ToList();
    }
}
Run Code Online (Sandbox Code Playgroud)

然后是这样的一个类

static class MyFruitKeys
{
    public const string Apple = "apple";
    public const string Plum = "plum";
    public const string Peach = "peach";
    public const int WillNotBeIncluded = -1;
}
Run Code Online (Sandbox Code Playgroud)

您可以获得如下string常量值:

List<string> result = typeof(MyFruitKeys).GetAllPublicConstantValues<string>();
//result[0] == "apple"
//result[1] == "plum"
//result[2] == "peach"
Run Code Online (Sandbox Code Playgroud)

  • 为什么不是这个: `.Where(fi =&gt; fi.IsLiteral &amp;&amp; !fi.IsInitOnly).Select(x =&gt; x.GetRawConstantValue()).OfType&lt;T&gt;().ToList();`? (4认同)

byt*_*dev 15

作为类型扩展:

public static class TypeExtensions
{
    public static IEnumerable<FieldInfo> GetConstants(this Type type)
    {
        var fieldInfos = type.GetFields(BindingFlags.Public | BindingFlags.Static | BindingFlags.FlattenHierarchy);

        return fieldInfos.Where(fi => fi.IsLiteral && !fi.IsInitOnly);
    }

    public static IEnumerable<T> GetConstantsValues<T>(this Type type) where T : class
    {
        var fieldInfos = GetConstants(type);

        return fieldInfos.Select(fi => fi.GetRawConstantValue() as T);
    }
}
Run Code Online (Sandbox Code Playgroud)