2010-08-06 23 views
21

Esto puede parecer un poco al revés, pero lo que quiero poder hacer es obtener un valor enum de una enumeración mediante su atributo Descripción.Encontrar un valor enum por su Descripción Atributo

Por lo tanto, si tengo una enumeración declara como sigue:

enum Testing 
{ 
    [Description("David Gouge")] 
    Dave = 1, 
    [Description("Peter Gouge")] 
    Pete = 2, 
    [Description("Marie Gouge")] 
    Ree = 3 
} 

me gustaría ser capaz de obtener 2 volver al suministrar la cadena "Peter Gouge".

Como punto de partida, que se pueden recorrer los campos de enumeración y agarrar el campo con el atributo correcto:

string descriptionToMatch = "Peter Gouge"; 
FieldInfo[] fields = typeof(Testing).GetFields(); 

foreach (FieldInfo field in fields) 
{ 
    if (field.GetCustomAttributes(typeof(DescriptionAttribute), false).Count() > 0) 
    { 
     if (((DescriptionAttribute)field.GetCustomAttributes(typeof(DescriptionAttribute), false)[0]).Description == descriptionToMatch) 
     { 

     } 
    } 
} 

Pero entonces yo estoy atascado en cuanto a qué hacer en ese caso interno. También no estoy seguro de si este es el camino a seguir en primer lugar.

Respuesta

27

Usando el método de extensión describe here:

Testing t = Enum.GetValues(typeof(Testing)) 
       .Cast<Testing>() 
       .FirstOrDefault(v => v.GetDescription() == descriptionToMatch); 

Si no se encuentra ningún valor coincidente, volverá (Testing)0 (es posible que desee para definir un miembro None en su enumeración de este valor)

+1

Ahh, LINQ al rescate una vez más. Me gusta mucho esta solución, ¡gracias! – DavidGouge

+0

-1: objetos extra creados en este código: 1) un RuntimeType, 2) un cast-iterator, 3) un objeto lambda, 4) un WhereIterator. Objetos extra creados con la solución de Ani; ninguna. – Henrik

+0

@Henrik, solo te estás olvidando de una cosa: la solución de Ani supone que ya tienes el FieldInfo, y necesitas usar el reflejo para obtenerlo ... Mi solución no utiliza el reflejo; GetValues ​​se implementa internamente con código nativo, por lo que es mucho más rápido que usar el reflejo (al menos 5 veces más rápido según mis pruebas). El costo de crear un RuntimeType y un WhereIterator es insignificante en comparación con la reflexión. En cuanto al "objeto lambda", no existe tal cosa ... es solo un método anónimo creado en el tipo actual. –

1

Ok, después de escribir todo eso, creo que este es un caso de decisión al principio que me lleva por el camino equivocado. Enum parecía ser el camino correcto para comenzar, ¡pero un simple Dictionary<string, int> será suficiente y será mucho más fácil trabajar con él!

4
return field.GetRawConstantValue(); 

Por supuesto, podría devolverlo a Prueba si es necesario.

+1

Excelente, gracias. – DavidGouge

+0

Parece prometedor, pero no funciona. Obtengo una 'InvalidOperationException':" La operación no es válida debido al estado actual del objeto ". –

+0

Acabo de echar un vistazo en Reflector: la única clase que realmente implementa este método es 'MdFieldInfo'. En 'RtFieldInfo', solo arroja una InvalidOperationException. –

Cuestiones relacionadas