Mapping enumerations to values of arbitrary type

Today is the first time i checked my blog after being out of country for 2 weeks. One thing i found surprising is that i still get legitimate traffic while not having much content. I guess that’s a good thing. I’m glad somebody finds these tiny bits interesting or helpful.

Either way, I recently worked on a tiny reusable library, which communicates with a legacy database. In short, the library is responsible for creating a transaction, which is simply an aggregation of a bunch of inserts, for a larger business process.

The most irritating thing about this is that while the process isn’t very difficult, it relies on a gazillion different status codes, most of which aren’t available through a look-up table. My goal was to document the process through an API.

The obvious choice here is to use enumeration to describe these codes. However, I also wanted to map each enumeration field to its equivalent code so that I can easily convert it back when necessary. Here is what I’m talking about.

public enum MyIntEnum
{
    [EnumMapper(1)]
    One,
    [EnumMapper(2)]
    Two
}

public enum MyStringEnum
{
    [EnumMapper("One")]
    One,
    [EnumMapper("Two")]
    Two
}

I’m using field attributes to hold the code value, which can be of any type. Here is the attribute class which implements all of the functionality i am looking for.

using System;
using System.ComponentModel;
using System.Linq;

[AttributeUsage(AttributeTargets.Field)]
public class EnumMapper : Attribute
{
    public EnumMapper(object value)
    {
        Value = value;
    }

    public object Value
    {
        get;
        private set;
    }

    public static T GetEnumValueAs<T>(Enum value)
    {
        var output = default(T);
        var enumType = value.GetType();
        var fieldInfo = enumType.GetField(value.ToString());
        var attributes = fieldInfo.GetCustomAttributes(typeof(EnumMapper), false) as EnumMapper[];

        if (attributes.Any())
        {
            var attribute = attributes.First();

            TypeConverter tc = TypeDescriptor.GetConverter(typeof(T));
            output = (T)tc.ConvertFrom(attribute.Value);
        }
        else
        {
            throw new InvalidOperationException(string.Format("Enumeration field {0} not found.", value.ToString()));
        }

        return output;
    }
}

The meat of the class is in the GetEnumValueAs<T>(Enum value) {} method, which attempts to convert an enumeration field back to its code value. This method is used in the following manner (using enumeration examples above).

int intValue = EnumMapper.GetEnumValueAs<int>(MyIntEnum.One);
string stringValue = EnumMapper.GetEnumValueAs<string>(MyStringEnum.One);

Besides all of the reflection junk, the coolest part of the method is the TypeConverter and TypeDescriptor classes of System.ComponentModel namespace, which help me convert from one type to another. Nice little hidden gem! I don’t know where all of this would be useful outside of my case of dealing with old, crappy legacy back-end, but I thought it was interesting enough to be read by others.