Como posso obter um valor enum a partir de sua descrição?

Eu tenho um enum representando todos os códigos de assembly de material no sistema:

public enum EAssemblyUnit { [Description("UCAL1")] eUCAL1, [Description("UCAL1-3CP")] eUCAL13CP, [Description("UCAL40-3CP")] eUCAL403CP, // ... } 

No código legado em outra parte do sistema, tenho objects rotulados com strings que correspondem às descrições de enum. Dada uma dessas strings, qual é a maneira mais limpa de obter o valor enum? Eu imagino algo como:

 public EAssemblyUnit FromDescription(string AU) { EAssemblyUnit eAU =  return eAU; } 

Você precisaria fazer uma iteração em todos os campos estáticos do enum (é assim que eles são armazenados na reflection) encontrando o atributo Description para cada um … quando você identifica o correto, obtenha o valor do campo.

Por exemplo:

 public static T GetValue(string description) { foreach (var field in typeof(T).GetFields()) { var descriptions = (DescriptionAttribute[]) field.GetCustomAttributes(typeof(DescriptionAttribute), false); if (descriptions.Any(x => x.Description == description)) { return (T) field.GetValue(null); } } throw new SomeException("Description not found"); } 

(Isso é genérico apenas para torná-lo reutilizável para enums diferentes.)

Obviamente, você gostaria de armazenar em cache as descrições se estiver fazendo isso com um pouco de frequência, por exemplo:

 public static class DescriptionDictionary where T : struct { private static readonly Dictionary Map = new Dictionary(); static DescriptionDictionary() { if (typeof(T).BaseType != typeof(Enum)) { throw new ArgumentException("Must only use with enums"); } // Could do this with a LINQ query, admittedly... foreach (var field in typeof(T).GetFields (BindingFlags.Public | BindingFlags.Static)) { T value = (T) field.GetValue(null); foreach (var description in (DescriptionAttribute[]) field.GetCustomAttributes(typeof(DescriptionAttribute), false)) { // TODO: Decide what to do if a description comes up // more than once Map[description.Description] = value; } } } public static T GetValue(string description) { T ret; if (Map.TryGetValue(description, out ret)) { return ret; } throw new WhateverException("Description not found"); } } 
 public EAssemblyUnit FromDescription(string AU) { EAssemblyUnit eAU = Enum.Parse(typeof(EAssemblyUnit), AU, true); return eAU; } 

Você também pode usar o Humanizer para isso. Para obter a descrição, você pode usar:

 EAssemblyUnit.eUCAL1.Humanize(); 

e para obter o enum de volta a partir da descrição que você pode usar

 "UCAL1".DehumanizeTo(); 

Disclaimer: Eu sou o criador do Humanizer.