Ответ 1
Я думаю, что метод Enum.ToObject
сделает то, что вы хотите.
Type type= typeof(Foo);
object o1 = Enum.ToObject(type,GetValue());
Предположим, что у нас есть перечисление:
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
и unbox как int
, или поле как int
и unbox как Foo
довольно счастливо)
Однако (проблема); если тип перечисления известен только во время выполнения, вещи... сложнее. Очевидно, тривиально помещать его как int
- но могу ли я вставить его как Foo
? (В идеале без использования дженериков и MakeGenericMethod
, что было бы уродливо). Convert.ChangeType
выдает исключение. ToString
и Enum.Parse
работает, но ужасно неэффективен.
Я мог бы посмотреть на определенные значения (Enum.GetValues
или Type.GetFields
), но это очень сложно для [Flags]
, и даже без этого потребуется сначала вернуться к первому типу (что не так сложно, к счастью).
Но; существует ли более прямое значение, чтобы получить значение правильного базового типа в поле типа перечисления, где тип известен только во время выполнения?
Я думаю, что метод Enum.ToObject
сделает то, что вы хотите.
Type type= typeof(Foo);
object o1 = Enum.ToObject(type,GetValue());
Просто хотел добавить что-то к @aaronb 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;
}
Если вы никогда не можете иметь тип с нулевым значением, просто игнорируйте это.:)