2010-01-06

Enums and String values

Recently, I had the need to set string values for enums, instead of using int values. Browsing the web, I came to Stefan Sedich’s blog, which had a very interesting article on creating string value attributes for enums. The article explained how to assign a custom string attribute to each enum value, and then how to get that string value from the enum by using reflection.

The article, as I said, was great, but it was missing one thing: working the other way around. I mean, it explained how to get the string value from the enum, but not how to get the enum value from the string. I needed both "ends" of the feature, With the help of a CodeProject article I found, I got to implement it succesfully.

So, to tell the whole story, here's how it basically works:

First, create a custom Attribute (a class that inherits the Attribute class)

  1: public class StringValueAttribute : Attribute
  2: {
  3:     /// <summary>
  4:     /// Holds the stringvalue for a value in an enum.
  5:     /// </summary>
  6:     public string StringValue { get; protected set; }
  7: 
  8:     /// <summary>
  9:     /// Constructor used to init a StringValue Attribute
 10:     /// </summary>
 11:     /// <param name="value"></param>
 12:     public StringValueAttribute(string value)
 13:     {
 14:         this.StringValue = value;
 15:     }
 16: }
Second, add the attribute to each one of your enum values:
  1: public enum UserState
  2: {
  3:     [StringValueAttribute("A")]
  4:     Active,
  5:     [StringValueAttribute("I")]
  6:     Inactive,
  7:     [StringValueAttribute("S")]
  8:     StandBy
  9: } 

Now, to get the associated string for a given enum value, you create an Extension Method for the Enum type:

  1: public static string GetStringValue(this Enum value)
  2: {
  3:     // Get the type
  4:     Type type = value.GetType();
  5: 
  6:     // Get fieldinfo for this type
  7:     FieldInfo fieldInfo = type.GetField(value.ToString());
  8: 
  9:     // Get the stringvalue attributes
 10:     var attribs = 
 11:         fieldInfo.GetCustomAttributes(typeof(StringValueAttribute), false) 
 12:         as StringValueAttribute[];
 13: 
 14:     // Return the first if there was a match.
 15:     return attribs.Length > 0 ? attribs[0].StringValue : null;
 16: }

To get the string value for the enum, we just needed to call the extension method:

  1: string state = UserState.Inactive.GetStringValue();

As I already said. This was all posted in Stefan Sedich’s article.

Now to go the other way around, here's what we need to do:

Just as in the first extension method was for the enum type and returned a string, our new one will have to be for the string type and return an enum. Actually, because the method will be generic to any enum type, we'll return an object, which will have to be casted by the caller to the appropriate type. This is the code:

  1: public static object GetEnumStringValue(this string value, 
  2:     Type enumType, bool ignoreCase)
  3: {
  4:     object result = null;
  5:     string enumStringValue = null;
  6:     if (!enumType.IsEnum)
  7:         throw new ArgumentException
  8:             ("enumType should be a valid enum");
  9: 
 10:     foreach (FieldInfo fieldInfo in enumType.GetFields())
 11:     {
 12:         var attribs = 
 13:             fieldInfo.GetCustomAttributes(typeof(StringValueAttribute), false) 
 14:             as StringValueAttribute[];
 15:         //Get the StringValueAttribute for each enum member
 16:         if (attribs.Length > 0)
 17:             enumStringValue = attribs[0].StringValue;
 18: 
 19:         if (string.Compare(enumStringValue, value, ignoreCase) == 0)
 20:             result = Enum.Parse(enumType, fieldInfo.Name);
 21:     }
 22: 
 23:     return result;
 24: }

To call it, we'll go with something like this:

  1: UserState enu = (UserState)"A".GetEnumStringValue(typeof(UserState), true);
There you go, hope you find it useful.

3 comentarios:

  1. Este comentario ha sido eliminado por el autor.

    ResponderEliminar
  2. Here's an improved version of the GetEnumStringValue method, suggested by my friend Vicente Peña:

    http://hugonne.blogspot.com/2010/01/enums-and-string-values-improved.html

    ResponderEliminar
  3. Thanks for your comment on my blog!

    http://www.neilpullinger.co.uk/2009/10/example-useful-c-extension-functions.html

    Neil

    ResponderEliminar

Your tips and thoughts are always welcome, and they provide good motivation: