2012-04-21 36 views

回答

168

雖然這是一箇舊的代碼:

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 determine 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)); 
} 

Source

您可以輕鬆地將其轉換爲更清晰的代碼使用泛型和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(); 
} 

或用一條線:

type.GetFields(BindingFlags.Public | BindingFlags.Static | 
       BindingFlags.FlattenHierarchy) 
    .Where(fi => fi.IsLiteral && !fi.IsInitOnly).ToList(); 
+9

*我+ 1 *被在我甚至通過第二條線之前......我注意到你正在經歷每一步......以意向爲目的的設計目的......!當人們需要從中吸取教訓時,這很重要。我希望每個有你的經驗的人都能像你這樣做。 – LoneXcoder 2012-12-10 08:49:16

+3

我不確定關於IsLiteral和IsInitOnly的斷言。在測試看來,對於靜態只讀屬性IsLiteral總是假 - 因此IsLiteral是唯一需要檢查以查找常量的標誌,並且您可以忽略IsInitOnly。我嘗試過使用不同的字段類型(例如String,Int32)來查看這是否有所作爲,但沒有。 – 2015-05-05 09:55:02

+29

此外,要從FieldInfo獲取const的值,請使用GetRawConstantValue()。 – 2015-07-07 00:15:48

1

使用property.GetConstantValue()來獲得價值

+0

當你擁有房產時,情況可能就是這樣 - 但是,你是如何獲得房產的? – 2015-12-14 10:15:11

+1

在.Net 4.5中它是:'GetRawConstantValue()' – Chris 2016-03-11 20:16:03

10

爲類型的擴展名:

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); 
    } 
} 
+0

顯然這是如果你的常量在類型上都是字符串;-) – nashwan 2015-12-11 16:57:36

+0

爲什麼不能(a)使方法成爲通用的,(b)使方法返回'IEnumerable '而不是「IList」? – 2015-12-11 17:06:05

+0

@WaiHaLee - 完成:-)。儘管顯然它仍然假定所討論的類中的所有類型的常量類型都是T. – nashwan 2015-12-14 10:23:57

16

如果你想獲得的值的特定類型的所有常量,從目標類型,在這裏是一個擴展方法(此頁面上延伸一些問題的答案):

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

然後,對於一類這樣

static class MyFruitKeys 
{ 
    public const string Apple = "apple"; 
    public const string Plum = "plum"; 
    public const string Peach = "peach"; 
    public const int WillNotBeIncluded = -1; 
} 

您可以獲取string常數值如下:

List<string> result = typeof(MyFruitKeys).GetAllPublicConstantValues<string>(); 
//result[0] == "apple" 
//result[1] == "plum" 
//result[2] == "peach" 
相關問題