2010-08-25 4 views
34

У меня есть простой EnumПолучение значения Enum с помощью отражения

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

var testing = TestEnum.TestOne; 

И я хочу, чтобы получить его значение (3) с помощью отражения. Есть идеи, как это сделать?

+0

Ваши комментарии: В контексте, где вы в каком-либо смысле «имеете» значение «TestEnum.TestOne», вы уже имеете * значение «3». Что у вас на самом деле? – AakashM

ответ

38

Большой вопрос Матем.

Сценарий вопроса заключается в следующем:

У вас есть некоторые неизвестного типа перечисления и некоторые неизвестного значение этого типа, и вы хотите, чтобы получить основное числовое значение этого неизвестного значения ,

Это одна линии способ сделать это с помощью отражения:

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

Если значение случается TestEnum.TestTwo, то value.GetType() будет равен typeof(TestEnum), Enum.GetUnderlyingType(value.GetType()) будет равен typeof(int) и значения будет быть 3 (в коробке, см. http://msdn.microsoft.com/en-us/library/yz2be5wk.aspx для более подробной информации о значениях бокса и unboxing).

Зачем нужно писать такой код? В моем случае у меня есть программа, которая копирует значения из модели представления в модель. Я использую это во всех моих обработчиках в проекте ASP.NET MVC как часть очень чистой и элегантной архитектуры для написания обработчиков, у которых нет проблем безопасности, которые обрабатывают обработчики, созданные шаблонами Microsoft.

Модель генерируется Entity Framework из базы данных и содержит поле типа int. В viewmodel есть поле некоторого типа перечисления, назовем его RecordStatus, который я определил в другом месте в моем проекте. Я решил полностью поддержать перечисления в моих рамках. Но теперь существует несоответствие между типом поля в модели и типом соответствующего поля в модели viewmodel. Мой код обнаруживает это и преобразует перечисление в int, используя код, аналогичный приведенному выше одному слою.

+3

Ваш ответ - хороший ответ на вопрос, который вы задавали себе, но я не думаю, что это ответ на заданный здесь вопрос. – hvd

+6

Спасибо за комментарий, но на самом деле это * есть * ответ на вопрос, который задавал Мать. –

+3

Более конкретно, Мат спросил, как он может получить (базовое) значение (3) значения перечисления (тестирования) некоторого простого типа перечисления (TestEnum) * с использованием отражения *. Дэниел и Фредрик предположили, что он спрашивает не то, что говорит, и ответил, что отражение необязательно, и Пранай ответил на другой вопрос вообще (как перечислить значения типа перечисления с использованием отражения). Именно из-за того, что ответы на данный момент не отвечают на вопрос, я перефразировал его, ответил на него и привел пример ситуации, когда можно было бы точно сказать, о чем спрашивал Мат! :-) –

1

Нет необходимости отражения:

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

еще раз я знаю, как это сделать. но мне нужно использовать рефлексию –

+6

@mjmcloug: если вы продлеваете свой вопрос с краткой информацией о * почему * вам нужно использовать отражение и ваш прецедент, вы получите лучшие ответы :) –

5

Зачем вам нужен отражение?

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

Великие мысли думают одинаково. И на той же секунде кажется :) –

+6

;) Да, я знаю, как это сделать.Но мне нужно использовать отражение –

+2

Это потому, что мы не знаем тип TestEnum, мы просто знаем, что у нас есть перечисление. –

16

Полный код: 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

Я не сделал -1, но я бы предположил, что хотя ответ правильный, это не очень описательно. Вот ссылка и какой-то код, понять это. Его можно было бы улучшить в нескольких отношениях, одним из которых было бы обеспечение вывода проб. –

-1

Или, если вам необходимо фактическое перечисление объекта (типа 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

Вы можете использовать Систему.Enum хелперы:

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); 
} 

Выходы

+4

Это лучший ответ. Потому что я пришел с таким же вопросом здесь, и я понял, что это проблема XY. Отражение было не тем, что мне нужно. – Bitterblue

+1

Я получаю эту ошибку «Необработанное исключение типа« System.InvalidCastException »при приведении в int (.Net 4.5). –

+4

Не все перечисления - это ints! Перечисления также могут быть sbyte, byte, short, ushort, uint, long, ulong и char. Как следует из принятого ответа, вы должны использовать базовый тип. –

2

Попробуйте следующее:

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

Просто простой.

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

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

Привет у вас есть эта альтернатива:

Type typevar = GetType([YourEnum])

А потом ... ... Вы можете получить имена с помощью typevar.GetEnumNames возвращает массив с именами и получить значение с помощью type.GetEnumValues, возвращая массив со значениями.

-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 

Это работает

+0

Но это не C# –

0

В моем случае проблема была MyEnum не найден из-за знаком + проникающего типа из сборки (строка 2):

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

Для вашего требования это, как просто, как уже указывали люди. Просто переведите объект enum в int и вы получите числовое значение перечисления.

int value = (int) TestEnum.TestOne; 

Однако, если есть необходимость смешать значения перечисления с | (побитовое ИЛИ), например.

var value = TestEnum.TestOne | TestEnum.TestTwo; 

и вы хотите, чтобы получить то, что варианты, которые смешивают вниз значение представляет, вот как вы можете это сделать (примечание: это для перечислений, что представленных Int значений, предназначенных, чтобы воспользоваться поразрядным operatations):

сначала введите параметры перечисления вместе со своими значениями в словаре.

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

Отфильтровать словарь, чтобы возвращать только смешанные варианты.

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

выполнить любую логику с вашими вариантами. например распечатывая их, превращая их в Список и т. д.:

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

надеюсь, что это поможет.

Смежные вопросы