2012-04-21 13 views

Odpowiedz

168

Mimo to stary kod:

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

można łatwo przekształcić go czystsze kod za pomocą leków generycznych i 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(); 
} 

lub jednym wierszu:

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

* My + 1 * została zanim zdążyłem przejść drugą linię ... i zauważyłem, że przechodzisz każdy krok z jego ... zamierzonym celem projektu ...! jest to ** TAK ** ważne, gdy trzeba się z niego uczyć. Chciałbym, aby każdy z twoim doświadczeniem robił tak, jak ty tutaj. – LoneXcoder

+3

Nie jestem pewien co do stwierdzeń dotyczących IsLiteral i IsInitOnly. Podczas testowania wydaje się, że dla statycznych właściwości readonly IsLiteral ma zawsze wartość false - dlatego IsLiteral jest jedyną flagą, którą należy sprawdzić, aby znaleźć stałe i można zignorować IsInitOnly. Próbowałem z różnymi typami pól (np. String, Int32), aby zobaczyć, czy to miało jakąkolwiek różnicę, ale tak się nie stało. –

+29

Ponadto, aby uzyskać wartość const z FieldInfo, należy użyć GetRawConstantValue(). –

1

użycie property.GetConstantValue(), aby uzyskać wartość

+0

Może się tak zdarzyć, gdy * masz * własność - ale * jak * otrzymujesz nieruchomość? –

+1

W .Net 4.5 to: 'GetRawConstantValue()' – Chris

10

Jako rozszerzeń Rodzaj:

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

Oczywiście jest tak, jeśli twoje stałe na typie są wszystkimi ciągami ;-) – nashwan

+0

Dlaczego nie (a) nie uczynić metod ogólnymi, (b) sprawić, by metody zwracały 'IEnumerable ' zamiast "IList"? –

+0

@WaiHaLee - Zrobione :-). Chociaż oczywiście nadal zakłada, że ​​wszystkie typy stałych w danej klasie są typu T. – nashwan

16

Jeśli chcieliby Państwo uzyskać wartości wszystkich stałych określonego typu, od rodzaju docelowej, tutaj jest to metoda rozszerzenie (rozszerzenie niektórych odpowiedziach na tej stronie):

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

Następnie dla klasy jak ten

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

można uzyskać string wartości stałych tak:

List<string> result = typeof(MyFruitKeys).GetAllPublicConstantValues<string>(); 
//result[0] == "apple" 
//result[1] == "plum" 
//result[2] == "peach" 
Powiązane problemy