Подтвердить что ты не робот

Получение значения Enum посредством отражения

У меня есть простой Enum

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

var testing = TestEnum.TestOne;

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

4b9b3361

Ответ 1

Великий вопрос Мать.

Сценарий вопроса таков:

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

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

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, используя код, аналогичный приведенному выше одному слою.

Ответ 2

Вы можете использовать помощники System.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);
}

Выходы

3
4

Ответ 4

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

int value = (int)TestEnum.TestOne;

Ответ 5

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

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

Ответ 6

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

int value = (int) TestEnum.TestOne;

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

var value = TestEnum.TestOne | TestEnum.TestTwo;

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

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

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

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

Ответ 7

Не нужно отражать:

int value = (int)TestEnum.TestOne;

Ответ 8

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

Type typevar = GetType([YourEnum])

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

Ответ 9

Эта статья лучше всего для вас использовать отражение с Enums:  Enum Reflection

Ответ 10

Просто.

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

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

Ответ 11

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

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

Ответ 12

Или, если вам нужен фактический объект перечисления (типа 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";
}

Ответ 13

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

Это работает