2010-08-25 11 views
34

Tengo una enumeración sencillaObtener valor de enumeración a través de la reflexión

public enum TestEnum 
{ 
    TestOne = 3, 
    TestTwo = 4 
} 

var testing = TestEnum.TestOne; 

Y Quiero recuperar su valor (3) a través de la reflexión. ¿Alguna idea sobre cómo hacer esto?

+0

A sus comentarios: En un contexto donde en cualquier sentido 'tiene' el valor 'TestEnum.TestOne', * ya tiene * el valor' 3'. ¿Qué es lo que realmente tienes? – AakashM

Respuesta

38

Gran pregunta Mat.

El escenario de la cuestión es la siguiente:

Tiene alguna desconocida tipo de enumeración y algunos valor desconocido de ese tipo y que desea obtener el valor numérico subyacente de ese valor desconocido .

Esta es la forma de una línea de hacer esto utilizando la reflexión:

object underlyingValue = Convert.ChangeType(value, Enum.GetUnderlyingType(value.GetType())); 

Si el valor pasa a ser TestEnum.TestTwo, a continuación, value.GetType() sería igual a typeof(TestEnum), Enum.GetUnderlyingType(value.GetType()) sería igual a typeof(int) y el valor sería ser 3 (en caja, ver http://msdn.microsoft.com/en-us/library/yz2be5wk.aspx para más detalles sobre boxeo y valores de unboxing).

¿Por qué alguna vez necesitaría escribir tal código? En mi caso, tengo una rutina que copia valores de un modelo de vista a un modelo. Utilizo esto en todos mis manejadores en un proyecto ASP.NET MVC como parte de una arquitectura muy limpia y elegante para escribir manejadores que no tienen los problemas de seguridad que los controladores generados por las plantillas de Microsoft.

El modelo es generado por Entity Framework desde la base de datos y contiene un campo de tipo int. El modelo de vista tiene un campo de tipo enum, vamos a llamarlo RecordStatus, que he definido en otro lugar de mi proyecto. Decidí apoyar las enumeraciones completamente en mi marco. Pero ahora hay una falta de coincidencia entre el tipo de campo en el modelo y el tipo del campo correspondiente en el modelo de vista. Mi código detecta esto y convierte la enumeración en un int usando el código similar al delineador dado arriba.

+3

Su respuesta es una buena respuesta a la pregunta que se hacía, pero no creo que sea una respuesta a la pregunta que se hace aquí. – hvd

+6

Gracias por el comentario, pero en realidad esta * es * la respuesta a la pregunta que estaba haciendo Mat. –

+3

Más específicamente, Mat preguntó cómo puede obtener el valor (subyacente) (3) de un valor enum (prueba) de algún tipo de enumeración simple (TestEnum) * utilizando reflection *. Daniel y Fredrik supusieron que estaba haciendo una pregunta incorrecta y respondieron que la reflexión es innecesaria y Pranay respondió una pregunta diferente (cómo enumerar los valores de un tipo de enumeración utilizando la reflexión). ¡Fue exactamente porque las respuestas actualizadas no responden a la pregunta formulada, la reformulé, respondí y dí un ejemplo de una situación en la que uno podría querer hacer exactamente lo que Mat estaba preguntando! :-) –

1

No hay necesidad de reflexión:

int value = (int)TestEnum.TestOne; 
+0

una vez más, sé cómo hacerlo de esta manera. pero necesito usar el reflejo –

+6

@mjmcloug: si amplía su pregunta con una breve información sobre * por qué * necesita usar la reflexión y su caso de uso, obtendrá mejores respuestas :) –

5

¿Por qué necesita la reflexión?

int value = (int)TestEnum.TestOne; 
+1

Las mentes geniales piensan igual. Y en el mismo segundo, parece :) –

+6

;) Sí, sé cómo hacerlo de esta manera.Pero necesito usar el reflejo –

+2

Es porque no conocemos el tipo TestEnum, solo sabemos que tenemos una enumeración. –

16

código completo: How to Get Enum Values with Reflection in C#

MemberInfo[] memberInfos = typeof(MyEnum).GetMembers(BindingFlags.Public | BindingFlags.Static); 
string alerta = ""; 
for (int i = 0; i < memberInfos.Length; i++) { 
alerta += memberInfos[i].Name + " - "; 
alerta += memberInfos[i].GetType().Name + "\n"; 
} 
+10

No lo hice, pero supongo que, aunque la respuesta es correcta, no es muy descriptivo. Aquí hay un enlace y un código, descárguelo. Podría mejorarse de varias maneras, una de las cuales sería proporcionar una muestra de salida. –

-1

O bien, si necesitaba el objeto de enumeración real (de tipo TestEnum):

MemberInfo[] memberInfos = typeof(MyEnum).GetMembers(BindingFlags.Public | BindingFlags.Static); 
string alerta = ""; 
for (int i = 0; i < memberInfos.Length; i++) { 

alerta += memberInfos[i].Name + " - "; 


/* alerta += memberInfos[i].GetType().Name + "\n"; */ 

// the actual enum object (of type MyEnum, above code is of type System.Reflection.RuntimeFieldInfo) 
object enumValue = memberInfos[i].GetValue(0); 
alerta += enumValue.ToString() + "\n"; 
} 
19

Puede usar el sistema.ayudantes de enumeración:

System.Type enumType = typeof(TestEnum); 
System.Type enumUnderlyingType = System.Enum.GetUnderlyingType(enumType); 
System.Array enumValues = System.Enum.GetValues(enumType); 

for (int i=0; i < enumValues.Length; i++) 
{ 
    // Retrieve the value of the ith enum item. 
    object value = enumValues.GetValue(i); 

    // Convert the value to its underlying type (int, byte, long, ...) 
    object underlyingValue = System.Convert.ChangeType(value, enumUnderlyingType); 

    System.Console.WriteLine(underlyingValue); 
} 

salidas

+4

Esta es la mejor respuesta. Porque vine con la misma pregunta aquí y me di cuenta de que era un problema XY. La reflexión no era lo que necesitaba. – Bitterblue

+1

Recibo este error "Excepción no controlada del tipo 'System.InvalidCastException'" al convertir a int (.Net 4.5). –

+4

¡No todas las enumeraciones son ints! Los mensajes también pueden ser sbyte, byte, short, ushort, uint, long, ulong y char. Debes lanzar al tipo subyacente, como sugiere la respuesta aceptada. –

2

intente lo siguiente:

System.Array enumValues = System.Enum.GetValues(typeof(MyEnum)); 
Type underlyingType = System.Enum.GetUnderlyingType(MyEnum); 

foreach (object enumValue in enumValues) 
    System.Console.WriteLine(String.Format("{0}",Convert.ChangeType(enumValue ,underlyingType))); 
0

simples.

var value = propertyInfo.GetValue(obj); // this return TestOne or TestTwo 

var enumValue = Convert.ChangeType(value, typeof(int)); // this return 3 or 4 
1

Hola que tienen esta alternativa:

Type typevar = GetType([YourEnum])

Y luego ... ... Puede obtener nombres usando typevar.GetEnumNames devolver una matriz con los nombres y para obtener valores utilizando type.GetEnumValues, devolviendo una matriz con valores.

-1
System.Type.GetType("Namespace Name" + "." + "Class Name" + "+" + "Enum Name") 

Dim fieldInfos() As System.Reflection.FieldInfo = System.Type.GetType("YourNameSpaceName.TestClass+TestEnum").GetFields 

For Each f As System.Reflection.FieldInfo In fieldInfos 
    If f.IsLiteral Then 
     MsgBox(f.Name & " : " & CType(f.GetValue(Nothing), Integer) & vbCrLf) 
    End If 
Next 

Public Class TestClass 
    Public Enum TestEnum 
     val1 = 20 
     val2 = 30 
    End Enum 
End Class 

que funciona

+0

Pero no es C# –

0

En mi caso, el problema se MyEnum no se ha encontrado debido a un signo + conseguir el tipo de montaje (línea 2):

var dll = System.Reflection.Assembly.LoadFile("pathToDll"); 
Type myEnum = dll.GetType("namespace+MyEnum"); 
System.Array myEnumValues = System.Enum.GetValues(myEnum); 
2

Para su requisito es tan simple como la gente ya lo señaló. Simplemente envía el objeto enum a int y obtendrías el valor numérico de la enumeración.

int value = (int) TestEnum.TestOne; 

Sin embargo, si es necesario mezclar los valores de enum con | (OR bit a bit) p.

var value = TestEnum.TestOne | TestEnum.TestTwo; 

y desea obtener lo que las opciones que mezclaba abajo valor representa, aquí es cómo usted podría hacerlo (nota: esto es para las enumeraciones que representados por valores int destinados para aprovechar operatations bit a bit):

primero, obtenga las opciones de enumeración junto con sus valores en un diccionario.

var all_options_dic = typeof(TestEnum).GetEnumValues().Cast<object>().ToDictionary(k=>k.ToString(), v=>(int) v); 

Filtra el diccionario para devolver solo las opciones mixtas.

var filtered = all_options_dic.Where(x => (x.Value & (int) options) != 0).ToDictionary(k=>k.Key, v=>v.Value); 

hagan cualquier lógica con sus opciones. p.ej. imprimiéndolos, convirtiéndolos en List, etc.:

foreach (var key in filtered.Keys) 
     { 
      Console.WriteLine(key + " = " + filtered[key]); 
     } 

Espero que esto ayude.

Cuestiones relacionadas