178 votes

Comment puis-je obtenir toutes les constantes d'un type par réflexion ?

Comment puis-je obtenir toutes les constantes de n'importe quel type en utilisant la réflexion ?

5 votes

319voto

gdoron Points 61066

Bien que ce soit un vieux code :

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

    FieldInfo[] fieldInfos = type.GetFields(
        // Obtient tous les champs publics et statiques

        BindingFlags.Public | BindingFlags.Static | 
        // Cela indique de récupérer les champs de tous les types de base également

        BindingFlags.FlattenHierarchy);

    // Parcourir la liste et ne choisir que les constantes
    foreach(FieldInfo fi in fieldInfos)
        // IsLiteral détermine si sa valeur est écrite à
        //   temps de compilation et non modifiable
        // IsInitOnly détermine si le champ peut être défini
        //   dans le corps du constructeur
        // pour C# un champ qui a le mot-clé readonly aurait true pour les deux 
        //   mais un champ const aurait seulement IsLiteral égal à true
        if(fi.IsLiteral && !fi.IsInitOnly)
            constants.Add(fi);           

    // Retourne un tableau de FieldInfos
    return (FieldInfo[])constants.ToArray(typeof(FieldInfo));
}

Source

Vous pouvez facilement le convertir en code plus propre en utilisant des génériques et LINQ :

private List 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 seule ligne :

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

18 votes

Mon +1 était avant même que je n'ai franchi la 2ème ligne .. j'ai remarqué que vous suivez chaque étape avec son ... but prévu par conception... ! C'est tellement important lorsque l'on a besoin d'apprendre de cela. Je souhaite que tout le monde avec votre expérience fasse comme vous l'avez fait ici.

4 votes

Je ne suis pas sûr des assertions concernant IsLiteral et IsInitOnly. En testant, il semble que pour les propriétés statiques en lecture seule, IsLiteral est toujours faux - donc IsLiteral est le seul indicateur que vous devez vérifier pour trouver les constantes et vous pouvez ignorer IsInitOnly. J'ai essayé avec différents types de champs (par exemple, chaîne, Int32) pour voir si cela faisait une différence mais ce n'était pas le cas.

57 votes

Aussi, pour obtenir la valeur de la constante à partir de FieldInfo, utilisez GetRawConstantValue().

101voto

BCA Points 369

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 sur cette page) :

public static class TypeUtilities
{
    public static List GetAllPublicConstantValues(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();
    }
}

Ensuite, 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 valeurs constantes de type string de cette manière :

List result = typeof(MyFruitKeys).GetAllPublicConstantValues();
//result[0] == "apple"
//result[1] == "plum"
//result[2] == "peach"

25voto

nashwan Points 314

En tant qu'extensions de Type :

public static class TypeExtensions
{
    public static IEnumerable 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 GetConstantsValues(this Type type) where T : class
    {
        var fieldInfos = GetConstants(type);

        return fieldInfos.Select(fi => fi.GetRawConstantValue() as T);
    }
}

4voto

Reza Bayat Points 333

Utilisez property.GetConstantValue() pour obtenir la valeur.

-1voto

public class Constants
{
    public class InputType
    {
        public const string DOCUMENTPHOTO = "document-photo";
        public const string SELFIEPHOTO = "selfie-photo";
        public const string SELFIEVIDEO = "selfie-video";
        public static List Domain { get { return typeof(Constants.InputType).GetAllPublicConstantValues(); } }
    }
    public class Type
    {
        public const string DRIVINGLICENSE = "driving-license";
        public const string NATIONALID = "national-id";
        public const string PASSPORT = "passport";
        public const string PROOFOFRESIDENCY = "proof-of-residency";
        public static List Domain { get { return typeof(Constants.Type).GetAllPublicConstantValues(); } }
    }
    public class Page
    {
        public const string FRONT = "front";
        public const string BLACK = "back";
        public static List Domain { get { return typeof(Constants.Page).GetAllPublicConstantValues(); } }
    }
    public class FileType
    {
        public const string FRONT = "selfie";
        public const string BLACK = "video";
        public const string DOCUMENT = "document";
        public const string MEDIA = "media";
        public const string CAPTCHA = "captcha";
        public const string DIGITALSIGNATURE = "digitalSignature";
        public static List Domain { get { return typeof(Constants.FileType).GetAllPublicConstantValues(); } }
    }
}

public static class TypeUtilities
{
    public static List GetAllPublicConstantValues(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();
    }
}

Utilisation : var inputTypeDomain = Constants.InputType.Domain;

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X