У меня есть простой Enum
public enum TestEnum
{
TestOne = 3,
TestTwo = 4
}
var testing = TestEnum.TestOne;
И я хочу получить его значение (3) через отражение. Любые идеи о том, как это сделать?
У меня есть простой Enum
public enum TestEnum
{
TestOne = 3,
TestTwo = 4
}
var testing = TestEnum.TestOne;
И я хочу получить его значение (3) через отражение. Любые идеи о том, как это сделать?
Великий вопрос Мать.
Сценарий вопроса таков:
У вас есть неизвестный тип перечисления и некоторое неизвестное значение этого типа, и вы хотите получить базовое числовое значение этого неизвестного значения.
Это однострочный способ сделать это с помощью отражения:
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, используя код, аналогичный приведенному выше одному слою.
Вы можете использовать помощники 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
Полный код: Как получить значения Enum с отражением в С#
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";
}
Зачем вам нужно отражение?
int value = (int)TestEnum.TestOne;
Попробуйте следующее:
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)));
Для вашего требования это так же просто, как люди уже указывали. Просто передайте объект 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]);
}
надеюсь, что это поможет.
Не нужно отражать:
int value = (int)TestEnum.TestOne;
Привет, у вас есть эта альтернатива:
Type typevar = GetType([YourEnum])
А потом...
...
Вы можете получить имена, используя typevar.GetEnumNames
, возвращая массив с именами и получая значения с помощью type.GetEnumValues
, возвращая массив со значениями.
Эта статья лучше всего для вас использовать отражение с Enums: Enum Reflection
Просто.
var value = propertyInfo.GetValue(obj); // this return TestOne or TestTwo
var enumValue = Convert.ChangeType(value, typeof(int)); // this return 3 or 4
В моем случае проблема заключалась в том, что MyEnum не был найден из-за того, что тип сборки + (см. строку 2):
var dll = System.Reflection.Assembly.LoadFile("pathToDll");
Type myEnum = dll.GetType("namespace+MyEnum");
System.Array myEnumValues = System.Enum.GetValues(myEnum);
Или, если вам нужен фактический объект перечисления (типа 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";
}
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
Это работает