Thursday, September 12, 2019

Converting Strings to Enums

In my last post I showed how to use the DescriptionAttribute to specify a customized value for an Enum value and I promised to show how to convert back to an Enum. Here it is, the FromDescription string extension method. This time I did remember to get the link from the SO answer I got this from. Thanks, max!
   1: public static T FromDescription(this string description)
   2: {
   3:   var type = typeof(T;
   4:   if (!type.IsEnum)
   5:   {
   6:     throw new InvalidOperationException($"{description} does not match any of the enumeration values);
   7:   }
   8: 
   9:   foreach (var field in type.GetFields())
  10:   {
  11:     if (Attribute.GetCustomAttribute(field, typeof(DescriptionAttribute)) is DescriptionAttribute attribute)
  12:     {
  13:       if (attribute.Description == description)
  14:       {
  15:         return (T)field.GetValue(null);
  16:       }
  17:     }
  18:     else
  19:     {
  20:       if (field.Name == description)
  21:       {
  22:         return (T)field.GetValue(null);
  23:       }
  24:     }
  25:   }
  26: 
  27:   throw new InvalidOperationException($"{description} does not match any of the enumeration values);
  28: }

Now that we have the extension method we can invoke it on any string, like this:
var contactType = "Phone Call".FromDescription<ContactTypes>();

Wednesday, September 11, 2019

Converting Enums to Strings

Yes, I'm aware you can easily get the string value of an Enum by using .ToString(). And that's great in many circumstances. I recently came across one where it was important to us to be able to translate an Enum to a custom string that included spaces (which you can't do with an Enum's value). I should have bookmarked the SO answer where I got this code from, but I didn't (sorry, Original Author, whoever you are!).

This extension method takes advantage of the built-in DescriptionAttribute. We decorate our Enum values with the DescriptionAttribute and provide whatever we want, like this:
   1: public enum ContactTypes
   2: {
   3:   [Description("Phone Call")]
   4:   Phone,
   5:   Email,
   6:   Chat
   7: }

Once we've decorated the Enum values, we'll need the extension method to get the description we just provided.
   1: public static string ToDescription(this Enum value)
   2: {
   3:   var da = (DescriptionAttribute[]) value.GetType().GetField(value.ToString()).GetCustomAttributes(typeof(DescriptionAttribute), false);
   4: 
   5:   return da.Length > 0 ? da[0].Description : value.ToString();
   6: }

Now we just need to use the extension method on our Enum to get the description we specified. Let's say we have a class that looks like this:
   1: public class Interaction
   2: {
   3:   public string UserName { get; set; }
   4: 
   5:   public ContactTypes ContactType { get; set; }
   6: }

If we wanted to get "Phone Call", "Email", and "Chat" returned (depending on which one was assigned in the class), we'd use the ToDescription extension method like this:
   1: var contact = new Interaction { ContactType = ContactTypes.Phone, UserName = "engineer-andrew" };
   2: var contactType = contact.ContactType.ToDescription();

Since we didn't use the DescriptionAttribute on Chat and Email, they'll default to just use .ToString() so they'd return "Chat" and "Email", respectively.
That's all there is to it. I know it's kinda simple, but I've used it a couple of times and my rule is to blog about those things. In the next post I'll show how to go the other way (take a string and find its matching Enum value).