通过反射获得枚举值

时间:2010-08-25 11:26:06

标签: c# reflection enums

我有一个简单的枚举

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

var testing = TestEnum.TestOne;

我想通过反射检索它的值(3)。关于如何做到这一点的任何想法?

15 个答案:

答案 0 :(得分:45)

很好的问题Mat。

问题的情景如下:

  

您有一些未知枚举类型和该类型的某些未知值,并且您希望获得该未知值的基础数值

这是使用反射执行此操作的单行方式:

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

为什么需要编写这样的代码?在我的例子中,我有一个例程,它将值从视图模型复制到模型。我在ASP.NET MVC项目中的所有处理程序中都使用它作为一个非常干净和优雅的体系结构的一部分,用于编写处理程序,这些处理程序没有Microsoft模板生成的处理程序所带来的安全问题。

模型由实体框架从数据库生成,它包含int类型的字段。 viewmodel有一个枚举类型的字段,让我们称之为RecordStatus,我在项目的其他地方定义了它。我决定在我的框架中完全支持枚举。但是现在模型中字段的类型与视图模型中相应字段的类型不匹配。我的代码检测到这一点并使用类似于上面给出的单行代码将枚举转换为int。

答案 1 :(得分:28)

您可以使用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

答案 2 :(得分:19)

完整代码: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";
}

答案 3 :(得分:6)

为什么需要反思?

int value = (int)TestEnum.TestOne;

答案 4 :(得分: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)));

答案 5 :(得分:2)

根据您的要求,它就像人们已经指出的一样简单。只需将枚举对象强制转换为int,就可以得到枚举的数值。

int value = (int) TestEnum.TestOne;

但是,如果需要将枚举值与|混合使用(按位OR)例如。

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

根据您的选择做任何逻辑。例如打印它们,将它们转换为List等。:

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

希望这会有所帮助。

答案 6 :(得分:1)

无需反思:

int value = (int)TestEnum.TestOne;

答案 7 :(得分:1)

嗨,你有这个选择:

Type typevar = GetType([YourEnum])

然后...... ... 您可以使用typevar.GetEnumNames获取名称,返回带有名称的数组,并使用type.GetEnumValues获取值,并返回包含值的数组。

答案 8 :(得分:0)

很简单。

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

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

答案 9 :(得分:0)

在我的情况下,问题是找不到MyEnum,因为汇编中的+符号类型(第2行):

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

答案 10 :(得分:0)

您可以使用Gethashkey函数获取类型未知的枚举的值。

Enum.Parse(enumType, enumvalue).GetHashCode();

更多详细信息

动态获取枚举类型

  private static Type GetEnumType(string enumName)
    {
            foreach (var assembly in AppDomain.CurrentDomain.GetAssemblies())
            {
                var type = assembly.GetType(enumName);
                if (type == null)
                    continue;
                if (type.IsEnum)
                    return type;
            }
        return null;
    }

读取枚举值

Enum.GetValues(enumType);

我希望它可以帮助某人!

答案 11 :(得分:0)

使用此方法通过反射获取enum int值

protected static object PropertyValue(object obj, string propertyName)
{
  var property = obj.GetType().GetProperty(propertyName);
  if(property == null)
    throw new Exception($"{propertyName} not found on {obj.GetType().FullName}");

  if (property.PropertyType.IsEnum)
    return (int) property.GetValue(obj);
  return property.GetValue(obj);
}

答案 12 :(得分:-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";
}

答案 13 :(得分:-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

有效

答案 14 :(得分:-1)

一定有动机提出这样的问题。在这里,我有一个现实生活中的场景,很有动力去做这样的事情以及解决这个问题的方法。

动机

2个带有循环引用的程序集。一种参考是硬参考,即项目文件中的<Reference . . .>标签。和相反方向的软参考。 assembly1必须调用assembly2中的某些对象和方法。方法的参数为enum

这是将获得枚举值的代码。程序集已在调用此方法时加载,因为包含该方法的对象实例已加载

解决方案

internal static object GetEnumValue(string assemblyName, string enumName, string valueName) // we know all these 
{
    var assembly = Assembly.Load(assemblyName);
    var converter = new EnumConverter(assembly.GetType(enumName)); 
    object enumVal = converter.ConvertFromString(valueName);
    return enumVal;
}

以及用法

dynamic myInstance = GetInstanceOfKnownObject(.......); // this preloads assembly for first time. All sequential loads are easy
dynamic enumArg = GetEnumValue("assemblyName", "assembly2.namespace1.EnumName", "enumValueName"); // important to load into 'dynamic', not 'object'
myInstance.MyMethod(enumArg);

底线-当一个程序集不了解(也不能了解)另一个程序集内部时,这真的很有用。