How to get all descriptions of enum values with reflection?

13,402

Solution 1

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

Solution 2

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.

Solution 3

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

Solution 4

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.

Share:
13,402
Harry89pl
Author by

Harry89pl

C#, ASP.NET MVC/ few years ago webforms, Silverlight, WPF, Winforms, XNA 4.0, Ext.Net controls, jQuery, WCF, Windows Phone 7.5 Check my personal token: https://personaltokens.io/CHAR Check my blog in polish: http://charubiniak.pl

Updated on July 13, 2022

Comments

  • Harry89pl
    Harry89pl almost 2 years

    So I need to get a List<string> from my enum

    Here is what I have done so far:

    enum definition

        [Flags]
        public enum ContractorType
        {
            [Description("Recipient")]
            RECIPIENT = 1,
            [Description("Deliver")]
            DELIVER = 2,
            [Description("Recipient / Deliver")]
            RECIPIENT_DELIVER = 4
        }
    

    HelperClass with method to do what I need:

    public static class EnumUtils
    {
        public static IEnumerable<string> GetDescrptions(Type enumerator)
        {
            FieldInfo[] fi = enumerator.GetFields();
    
            List<DescriptionAttribute> attributes = new List<DescriptionAttribute>();
            foreach (var i in fi)
            {
                try
                {
                    yield return attributes.Add(((DescriptionAttribute[])i.GetCustomAttributes(
                        typeof(DescriptionAttribute),
                        false))[0]);
                }
                catch { }
            }
            return new List<string>{"empty"};
        }
    }
    

    Now in the line where I yield values, I got a NullReferenceException. Did I miss something? The syntax looks all right to me, but maybe I overlooked something?

    Edit: I'm using .net Framework 4.0 here.