I love enums, they’re pretty and easy to use. I use them as often as I can. Recently, I was building an application where the data model had already been defined, and could not be changed. There was a Status column in several tables of type char(1). I nice fit for enums except that it was a character instead of an integer. How to overcome this? Attributes.
Here is a sample class.
public enum TrafficLight
{
Red = 1,
Green = 2,
Yellow = 3
}
The first problem is that the database stores this value as “R”, “G”, or “Y”. To overcome this we add an custom attribute to the enum:
public enum TrafficLight
{
[TrafficLightCode(”R”)]Red = 1,
[TrafficLightCode(”G”)]Green = 2,
[TrafficLightCode(”Y”)]Yellow = 3
}
Next we need to create a class for the attribute:
[AttributeUsage(AttributeTargets.Field)]
public class TrafficLightCode : System.Attribute
{
private string trafficLightCode;
public TrafficLightCode(string LightCode)
{
trafficLightCode = LightCode;
}
public string LightCode
{
get{return trafficLightCode;}
}
}
To convert between a TrafficLightCode from the database to a TrafficLight enum, and vice versa:
public static string GetLightCodeCode(Enum value)
{
FieldInfo fi = value.GetType().GetField(value.ToString());
if (fi != null)
{
TrafficLightCodeAttribute[] attributes = (TrafficLightCodeAttribute[])fi.GetCustomAttributes(typeof(TrafficLightCodeAttribute), false);
return (attributes.Length > 0) ? attributes[0].TrafficeLightCode : value.ToString();
}
else
{
return value.ToString();
}
}
And now the hard part, coverting the character code back to the Enum when retrieving the column back from the database:
public static TrafficLight GetEnum(string code)
{
// Get the members associated with Status.
FieldInfo[] fieldInfos = typeof(TrafficLight).GetFields();
// Loop thru each member of Status
for(int i = 0; i < fieldInfos.Length; i++)
{
//Some of the fields may not have an attribute
if ( fieldInfos[i].GetCustomAttributes(true).Length > 0)
{
FieldInfo fi = fieldInfos[i];
TrafficLightCodeAttribute[] attribute = (TrafficLightCodeAttribute[])fi.GetCustomAttributes(typeof(TrafficLightCodeAttribute), false);
//Check if it matches
if (attribute[0].TrafficeLightCode == code)
{
//Get the string value, convert it to the enum value, and return it
return (TrafficLight)Enum.Parse(typeof(TrafficLight), fi.Name);
}
}
}
throw new InvalidEnumArgumentException(”Code value of ” + code + ” was not found.”);
}
Additional Uses
I use this same technique of applying attributes to enums to create user-friendly descriptions of enums so I can bind an enum to a control, and use the value of the attribute as the display value. That approach is a little easier because the .Net Framework already has a built in Description Attribute. Further reading and code samples.