C# Extension Methods To Get Enum DescriptionAttributes And Other Custom Attributes

C# Extension Methods To Get Enum DescriptionAttributes And Other Custom Attributes

Thursday 23 April 2009

A quick code snippet.  These two extension methods (C# 3.0+) enables you to return custom attributes from types, both on a specific type and any data type.  They both return null if the attribute is not present.  

The first extension is useful for extending a type of your choice.  It's especially useful when considering Enums and the DescriptionAttribute, or other enumeration attributes (especially custom attributes).  The usage examples below should make the use more obvious.

The second extension allows you to return an Attribute from ANY type.  Use with caution, but I find it interesting that it's actually possible to write an extension method that works that way.

    public static class ElementExtensions
    {    

        public static T GetAttributeValue<T>(this SomeConcreteType val)
        {
            var attributes = val.GetType().GetField(val.ToString()).GetCustomAttributes(typeof(T), false);

            T response = default(T);
            if(attributes.Length > 0)
            {
                response = (T)attributes[0];
            }

            return response;
        }


        public static TReturnType GetAttributeValueFromType<TInstanceType, TReturnType>(this TInstanceType val)
        {
            var attributes = val.GetType().GetField(val.ToString()).GetCustomAttributes(typeof(TReturnType), false);

            TReturnType response = default(TReturnType);
            if(attributes.Length > 0)
            {
                response = (TReturnType)attributes[0];
            }

            return response;
        }       
    }   

Some usage examples....


    public enum RegexEnum
    {
        [RandomAttribute("^(([a-zA-Z]{1}[0-9]{3,4})|([a-zA-Z]{2}[0-9]{2,3})|[0-9]{4})$")]
        SomeEnumValue,
    }   


    public class RandomAttribute: Attribute
    {
        public string Expression { get; set; }

        public RandomAttribute(string expression)
        {
            Expression = expression;
        }
    }


    private static void Example()
    {
        // Both of these are equivalent
        foreach(var enumMember in Enum.GetValues(typeof(RegexEnum)))
        {
            var value = enumMember.GetAttributeValue();   
            var valueFromAnyType = enumMember.GetAttributeValueFromType<RegexEnum, RandomAttribute>();
        }       
    }


Some nice syntactic sugar for use with enumerations.