2010-04-17 4 views
34

Stellen wir eine ENUM haben:eine ganze Zahl in eine geschachtelte Aufzählungstyp Konvertieren nur zur Laufzeit bekannt

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

Wenn der Typ zum Zeitpunkt der Kompilierung bekannt ist, kann eine direkte Besetzung verwendet wird zwischen dem enum- zu ändern Typ und der zugrunde liegende Typ (in der Regel int):

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

und Boxen dies gibt einen Kasten vom Typ Foo:

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

(und in der Tat, können Sie als Foo und unbox als int Feld oder Feld als int und unbox als Foo ganz glücklich)

jedoch (das Problem); Wenn der Enum-Typ nur zur Laufzeit bekannt ist, sind die Dinge ... kniffliger. Es ist offensichtlich trivial, es als int Box - aber kann ich es als Foo Box? (Idealerweise ohne Generika und MakeGenericMethod, was hässlich wäre). Convert.ChangeType löst eine Ausnahme aus. ToString und Enum.Parse funktioniert, aber ist schrecklich ineffizient.

ich an den definierten Werten (Enum.GetValues oder Type.GetFields) aussehen könnte, aber das ist sehr schwer für [Flags], und auch ohne erfordern würde, um den darunter liegenden Typen immer wieder ersten (das ist nicht so schwer, zum Glück).

Aber; Gibt es einen direkteren Zugriff von einem Wert des richtigen zugrunde liegenden Typs auf eine Box des Enum-Typs, wobei der Typ nur zur Laufzeit bekannt ist?

Antwort

60

Ich denke, die Enum.ToObject Methode wird tun, was Sie wollen.

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

Wie die | $ (* &% $ (habe ich vermisse das! Danke, das ist genau das, was ich will. –

+3

Einfach zu verpassen. Scheint wie eine schreckliche Methode Name. So etwas wie 'Enum.FromValue' haben kann –

8

Ich wollte nur etwas zu @aaronb's answer hinzufügen: Ich habe dieses sehr, was für einige Auto-Mapping-Code zu tun hatte, und fand heraus, dass ich, um mehrere Kontrollen zu tun benötigt, um den Code Arbeit für beliebige Typen zu machen. Insbesondere Null-Werte und nullbare Enums werden Ihnen Kopfschmerzen bereiten.

Der sicherste Code, den ich im Moment haben, ist dies:

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

Wenn Sie noch nie ein Nullable Type haben dann diese einfach ignorieren. :)

+0

Wertvolle Gedanken, aber in der Tat habe ich bereits Dinge wie 'Nullable ', 'List ' usw. stromaufwärts von diesem entfernt. –

+0

'Nullable.GetUnderlyingType' könnte ein wenig einfacher als die Überprüfung der generischen Argumente sein. – Craig

Verwandte Themen