Comment puis-je obtenir toutes les constantes de tout type en utilisant la réflexion?
Comment puis-je obtenir toutes les constantes de tout type en utilisant la réflexion?
Réponses:
Bien que ce soit un ancien code:
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));
}
Vous pouvez facilement le convertir en code plus propre à l'aide de génériques et de 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();
}
Ou avec une ligne:
type.GetFields(BindingFlags.Public | BindingFlags.Static |
BindingFlags.FlattenHierarchy)
.Where(fi => fi.IsLiteral && !fi.IsInitOnly).ToList();
IsLiteral
dit if its value is written at compile time
et cela n'est vrai que pour les constantes, c'est ainsi qu'il se comporte maintenant (testé à partir de .NET 4.5.2)
Si vous souhaitez obtenir les valeurs de toutes les constantes d'un type spécifique, à partir du type cible, voici une méthode d'extension (étendant certaines des réponses de cette page):
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();
}
}
Alors pour une classe comme celle-ci
static class MyFruitKeys
{
public const string Apple = "apple";
public const string Plum = "plum";
public const string Peach = "peach";
public const int WillNotBeIncluded = -1;
}
Vous pouvez obtenir les string
valeurs constantes comme ceci:
List<string> result = typeof(MyFruitKeys).GetAllPublicConstantValues<string>();
//result[0] == "apple"
//result[1] == "plum"
//result[2] == "peach"
.Where(fi => fi.IsLiteral && !fi.IsInitOnly).Select(x => x.GetRawConstantValue()).OfType<T>().ToList();
:?
En tant qu'extensions de type:
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);
}
}
IEnumerable<T>
au lieu d'un IList
?
Utilisez property.GetConstantValue()
pour obtenir de la valeur.
GetRawConstantValue()