将整数转换为仅在运行时已知的盒装枚举类型

时间:2010-04-17 21:47:36

标签: c# .net reflection enums

想象一下,我们有一个枚举:

enum Foo { A=1,B=2,C=3 }

如果在编译时已知类型,则可以使用直接强制转换来在枚举类型和基础类型之间进行更改(通常为int):

static int GetValue() { return 2; }
...
Foo foo = (Foo)GetValue(); // becomes Foo.B

拳击会给出一个Foo类型的框:

object o1 = foo;
Console.WriteLine(o1.GetType().Name); // writes Foo

(实际上,您可以将Foo打开并将其打包为int,或将框打包为int,将打开的广告框设置为Foo非常高兴)

然而 (问题);如果枚举类型仅在运行时已知,那么事情就更棘手了。将其格式化为int显然是微不足道的 - 但是我可以将其设为Foo吗? (理想情况下不使用泛型和MakeGenericMethod,这将是丑陋的)。 Convert.ChangeType抛出异常。 ToStringEnum.Parse有效,但可能效率低下。

我可以查看已定义的值(Enum.GetValuesType.GetFields),但这对[Flags]非常困难,即使没有,也需要先返回基础类型(这不是那么难,谢天谢地。)

但;是否更直接从正确的底层类型的值获取到枚举类型的框,其中类型仅在运行时已知?

2 个答案:

答案 0 :(得分:70)

我认为Enum.ToObject方法会做你想要的。

Type type= typeof(Foo);
object o1 = Enum.ToObject(type,GetValue());

答案 1 :(得分:8)

只是想向@aaronb's answer添加一些内容:我必须对某些自动映射代码执行此操作,并发现我需要进行多项检查才能使代码适用于任意类型。特别是,空值和可空的枚举会让您头疼。

我目前最简单的代码是:

static object CastBoxedValue(object value, Type destType)
{
    if (value == null)
        return value;

    Type enumType = GetEnumType(destType);
    if (enumType != null)
        return Enum.ToObject(enumType, value);

    return value;
}

private static Type GetEnumType(Type type)
{
    if (type.IsEnum)
        return type;

    if (type.IsGenericType)
    {
        var genericDef = type.GetGenericTypeDefinition();
        if (genericDef == typeof(Nullable<>))
        {
            var genericArgs = type.GetGenericArguments();
            return (genericArgs[0].IsEnum) ? genericArgs[0] : null;
        }
    }
    return null;
}

如果你永远不能拥有可空类型,那么就忽略它。 :)