How to get all descriptions of enum values with reflection?

拟墨画扇 提交于 2019-12-03 16:29:06
Mario Stopfer

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.

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

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.

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()
Yusuf Uzun

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;
 }
COLD TOLD

You can try this

public string ContractorTypeDescription(Enum ContractorType)
{
    FieldInfo fi = ContractorType.GetType().GetField(ContractorType.ToString());
    var attributes = (DescriptionAttribute[])fi.GetCustomAttributes(typeof(DescriptionAttribute), false);
    if (attributes.Length > 0)
    {
        return attributes[0].Description;
    }
    else
    {
        return ContractorType.ToString();
    }
}

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;
        }
    }
}
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!