Enum to dictionary

Problem

In a previous project we stored the values of an enum in a database. That made it easy to fill listboxes and comboboxes. It also helps to ensure data integrity. Storing enums means a violations of the most important rule for developers: single point of definition.

Solution

A better option is a dictionary with easy to read descriptions.

Example of an enum:

                        
                                
      [DataContract]
      enum TestEnum
      {
          Value = 2,
          ADifferentValue,
          [EnumMember(Value = "Different description")]
          OriginalValue
      }
      
                        
                    

In this case you want a dictionary to fill the listboxes with the enum value as the key and these values:

  • Value
  • A different value
  • Different description

Note the extra spaces and lowercase characters.

This can be done this way:

                        
                                
      public static IDictionary<T, string> ConvertEnumToDictionaryEnumString<T>()
      {
          return ConvertEnumToDictionaryStringEnum<T>().ToDictionary(x => x.Value, y => y.Key);
      }
       
      public static IDictionary<string, T> ConvertEnumToDictionaryStringEnum<T>()
      {
          CheckIfTIsAnEnum<T>();
          var tValues = Enum.GetValues(typeof(T)).Cast<T>();
          return tValues.ToDictionary(c => GetDescriptionEnumObject(c));
      }
       
      private static void CheckIfTIsAnEnum<T>()
      {
          if (typeof(T).BaseType != typeof(Enum))
          {
              throw new InvalidCastException("The type must be an enum");
          }
      }
      
                        
                    

Now we still need to implement the GetDescriptionEnumObject() method. We could do that with regular expressions but that is is hard to debug so I did that the hard way:

                        
                                
      private static string GetDescriptionEnumObject(object enumObject)
      {
        string result;
        FieldInfo fieldInfo = enumObject.GetType().GetField(enumObject.ToString());
        var fieldInfoEnumMembers = (EnumMemberAttribute[])fieldInfo.GetCustomAttributes(typeof(EnumMemberAttribute), true);
        var fieldInfoEnumMember = fieldInfoEnumMembers.FirstOrDefault();
       
        if (fieldInfoEnumMember == null) // No EnumMember-Attribute
        {
            result = ConvertToReadableText(enumObject.ToString());
        }
        else // Has an EnumMember-Attribute
        {
            if (fieldInfoEnumMember.Value == null) // Attribute not filled with text
            {
                result = ConvertToReadableText(enumObject.ToString()); // Do the same as if there is no attribute
            }
            else // The attribute is filled with text
            {
                result = fieldInfoEnumMember.Value; // Return text in the attribute
            }
        }
        return result;
      }
       
      private static string ConvertToReadableText(string originalText)
      {
          if (originalText == null || originalText.Length < 2)
          {
              return originalText;
          }
       
          var collectionChars = originalText.Substring(1).Select(ConvertCharToReadableText); // Start on second position
          return originalText.Substring(0, 1) + String.Concat(collectionChars); // First char remains the same
      }
       
      private static string ConvertCharToReadableText(char original)
      {
          if (char.IsUpper(original)) <br>    {<br>        return String.Concat(" ", original.ToString(CultureInfo.InvariantCulture).ToLower());<br>     }
       
          return original.ToString();
      }
      
                        
                    

Optional

In case you also need an int-string dictionary:

                        
                                
      public static IDictionary<int, string> ConvertEnumToDictionaryIntString<T>()
      {
          // Swap Key en value 
          return ConvertEnumToDictionaryStringInt<T>().ToDictionary(x => x.Value, y => y.Key);
      }
 
      public static IDictionary<string, int> ConvertEnumToDictionaryStringInt<T>()
      {
        return ConvertEnumToDictionaryStringEnum<T>().ToDictionary(x => x.Key, y => Convert.ToInt32(y.Value));
      }
      
                        
                    

Example

                        
                                
      ConvertEnumToDictionaryEnumString<TestEnum>();
      
                        
                    

Leave a Comment

Comment

Comments