How to get all descriptions of enum values with reflection?

前端 未结 7 1470
孤独总比滥情好
孤独总比滥情好 2021-02-10 08:29

So I need to get a List from my enum

Here is what I have done so far:

enum definition

           


        
相关标签:
7条回答
  • 2021-02-10 08:52

    I created these extension methods

    public static class EnumExtender
    {
        public static string GetDescription(this Enum enumValue)
        {
            string output = null;
            Type type = enumValue.GetType();
            FieldInfo fi = type.GetField(enumValue.ToString());
            var attrs = fi.GetCustomAttributes(typeof(DescriptionAttribute), false) as DescriptionAttribute[];
            if (attrs.Length > 0) output = attrs[0].Description;
            return output;
        }
    
        public static IDictionary<T, string> GetEnumValuesWithDescription<T>(this Type type) where T : struct, IConvertible
        {
            if (!type.IsEnum)
            {
                throw new ArgumentException("T must be an enumerated type");
            }
    
            return type.GetEnumValues()
                    .OfType<T>()
                    .ToDictionary(
                        key => key,
                        val => (val as Enum).GetDescription()
                    );
        }
    }
    

    Usage

    var stuff = typeof(TestEnum).GetEnumValuesWithDescription<TestEnum>();
    

    Will return a Dictionary<TestEnum, string> with value as keys and descriptions as values. If you want just a list, you can change .ToDictionary to

    .Select(o => (o as Enum).GetDescription())
    .ToList()
    
    0 讨论(0)
  • 2021-02-10 09:01

    Here is a small reusable solution. This is an abstract class which will extract all the attributes of type K from type T.

    abstract class AbstractAttributes<T, K>
    {
        protected List<K> Attributes = new List<K>();
    
        public AbstractAttributes()
        {
            foreach (var member in typeof(T).GetMembers())
            {
                foreach (K attribute in member.GetCustomAttributes(typeof(K), true)) 
                    Attributes.Add(attribute);                
            }
        }
    }
    

    Should we now want to extract only attributes of DescriptionAttribute type, we would use the following class.

    class DescriptionAttributes<T> : AbstractAttributes<T, DescriptionAttribute>
    {
        public List<string> Descriptions { get; set; }
    
        public DescriptionAttributes()
        {
            Descriptions = Attributes.Select(x => x.Description).ToList();
        }
    }
    

    This class will extract only attributes of DescriptionAttribute type from the type T. But to actually use this class in you context you will simply need to do the following.

    new DescriptionAttributes<ContractorType>().Descriptions.ForEach(x => Console.WriteLine(x));
    

    This line of code will write out all the descriptions you used as parameters in your attributes of type DescriptionAttribute. Should you need to extract some other attributes, just create a new class that derives from the AbstractAttributes<T, K> class and close its type K with the appropriate attribute.

    0 讨论(0)
  • 2021-02-10 09:08

    It think this can solve your problem. If it is not implemented you can return null or an exception. It depends what you need.

    public DescriptionAttribute GetDescription(ContractorType contractorType)
    {
         MemberInfo memberInfo = typeof(ContractorType).GetMember(contractorType.ToString())
                                              .FirstOrDefault();
    
         if (memberInfo != null)
        {
             DescriptionAttribute attribute = (DescriptionAttribute) 
                     memberInfo.GetCustomAttributes(typeof(DescriptionAttribute), false)
                               .FirstOrDefault();
             return attribute;
        }
    
        //return null;
        //or
    
        throw new NotImplementedException("There is no description for this enum");
    }
    

    So you will use it like this :

    DescriptionAttribute attribute = GetDescription(ContractorType.RECIPIENT);
    

    Sorry that I didn't read your question. Here is some code that you can use to take all of the description strings:

     public IEnumerable<string> GetAllDescriptionInText()
     {
         List<string> descList = new List<string>();
         foreach (DescriptionAttribute desc in Enum.GetValues(typeof(DescriptionAttribute)))
         {
             descList.Add(GetDescription(desc).Value);
         }
         return descList;
     }
    
    0 讨论(0)
  • 2021-02-10 09:11

    This generic static method works fine for getting a list of descriptions for each value of an enum type of T:

    public static IEnumerable<string> GetDescriptions<T>()
    {
        var attributes = typeof(T).GetMembers()
            .SelectMany(member => member.GetCustomAttributes(typeof (DescriptionAttribute), true).Cast<DescriptionAttribute>())
            .ToList();
    
        return attributes.Select(x => x.Description);
    }
    
    0 讨论(0)
  • 2021-02-10 09:15

    You need to find the DescriptionAttribute on each field, if it exists and then retrieve the Description attribute e.g.

    return enumType.GetFields()
                    .Select(f => (DescriptionAttribute)f.GetCustomAttribute(typeof(DescriptionAttribute)))
                    .Where(a => a != null)
                    .Select(a => a.Description)
    

    If you could have multiple descriptions on a field, you could do something like:

    FieldInfo[] fields = enumType.GetFields();
    foreach(FieldInfo field in fields)
    {
        var descriptionAttributes = field.GetCustomAttributes(false).OfType<DescriptionAttribute>();
        foreach(var descAttr in descriptionAttributes)
        {
            yield return descAttr.Description;
        }
    }
    

    which is more similar to your existing approach.

    0 讨论(0)
  • 2021-02-10 09:15

    This is Dictionary not List
    But is is something I use

    using System.ComponentModel;
    using System.Reflection;
    using MyExtensions;
    
    namespace MyExtensions
    {
        public static class Extension
        {
            public static string GetDescriptionName(this Enum value)
            {
                Type type = value.GetType();
                string name = Enum.GetName(type, value);
                if (name == null)
                    return null;
                else
                {
                    FieldInfo field = type.GetField(name);
                    if (field == null)
                        return name;
                    else
                    {
                        DescriptionAttribute attr =
                                Attribute.GetCustomAttribute(field,
                                    typeof(DescriptionAttribute)) as DescriptionAttribute;
                        if (attr == null)
                            return name;
                        else
                            return attr.Description;
                    }
                }
            }
        }
    }
    
    namespace EnumDescription
    {
        class Program
        {
            public enum enumDateCond : byte 
            {
                [Description("Empty")]
                Null = 0,
                [Description("Not Empty")]
                NotNull = 1,
                EQ = 2, 
                LT = 3, 
                LE = 4, 
                GE = 14, 
                GT = 15 
            };
            static void Main(string[] args)
            {
                enumDateCond x = enumDateCond.Null;
                string description = x.GetDescriptionName();
                foreach (enumDateCond enm in Enum.GetValues(typeof(enumDateCond)))
                {
                    description = enm.GetDescriptionName();
                    Console.WriteLine(description);
                }
                Console.WriteLine("Dictionary");
                Dictionary<enumDateCond, string> DLenumDateCond = EnumToDictionary<enumDateCond>();
                foreach(enumDateCond key in DLenumDateCond.Keys)
                {
                    Console.WriteLine(key.ToString() + " " + DLenumDateCond[key]);
                }
            }
            public static Dictionary<T, string> EnumToDictionary<T>()
                where T : struct
            {
                Type enumType = typeof(T);
    
                // Can't use generic type constraints on value types,
                // so have to do check like this
                if (enumType.BaseType != typeof(Enum))
                    throw new ArgumentException("T must be of type System.Enum");
    
                Dictionary<T, string> enumDL = new Dictionary<T, string>();
                foreach (T enm in Enum.GetValues(enumType))
                {
                    string name = Enum.GetName(enumType, enm);
                    if (name != null)
                    {
                        FieldInfo field = enumType.GetField(name);
                        if (field != null)
                        {
                            DescriptionAttribute attr =
                                    Attribute.GetCustomAttribute(field,
                                        typeof(DescriptionAttribute)) as DescriptionAttribute;
                            if (attr != null)
                                name = attr.Description;
                        }
                    }
                    enumDL.Add(enm, name);
                }
                return enumDL;
            }
        }
    }
    
    0 讨论(0)
提交回复
热议问题