Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to get all descriptions of enum values with reflection?

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.

like image 590
Harry89pl Avatar asked Jun 02 '13 19:06

Harry89pl


People also ask

Does enum GetValues use reflection?

Roughly, yes. There are two kind of reflection code, the general kind that goes through RuntimeType and the specific kind that uses dedicated CLR helper functions.

How do I use enum GetValues?

The GetValues method returns an array that contains a value for each member of the enumType enumeration. If multiple members have the same value, the returned array includes duplicate values.


2 Answers

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);
}
like image 68
Thiago Silva Avatar answered Oct 03 '22 15:10

Thiago Silva


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.

like image 26
Mario Stopfer Avatar answered Oct 03 '22 16:10

Mario Stopfer