2015-03-04 20 views
6

Angenommen, ich weiß, dass Eigentum Color eines Objekts eine Aufzählung zurückgibt, wie diese aussieht:Wie überprüfe ich die enum-Eigenschaft, wenn die Eigenschaft von dynamic in C# abgerufen wird?

enum ColorEnum { 
    Red, 
    Green, 
    Blue 
}; 

und ich möchte überprüfen, ob ein bestimmtes Objekt unbekannter Art (die ich kenne Color Eigenschaft hat) hat Color Set zu Red. Dies ist, was ich tun würde, wenn ich den Objekttyp weiß:

ObjectType thatObject = obtainThatObject(); 
if(thatObject.Color == ColorEnum.Red) { 
    //blah 
} 

Das Problem ist, ich habe keinen Verweis auf die Assembly mit ColorEnum und weiß nicht, den Objekttyp.

Anstatt also habe ich die folgende Konfiguration:

dynamic thatObject = obtainThatObject(); 

und ich kann nicht werfen, weil ich nicht weiß, den Objekttyp (und den Aufzählungstyp). Wie sollte ich die überprüfen?

if(thatObject.Color.ToString() == "Red") { 
    //blah 
} 

funktioniert, aber es sieht aus wie die schlimmsten Beispiele für Cargo-Kult Code, den ich in "The Daily WTF" gesehen habe.

Wie überprüfe ich die Prüfung richtig?

+0

Kennen Sie alle möglichen Werte des Aufzählungstypen in der Seitenanordnung und die numerischen Darstellungen? –

+0

@YohDeadfall Ich würde mich lieber nicht darauf verlassen - niemand weiß, was sich dort ändert. – sharptooth

+0

haben Sie Einfluss auf die 'requireThatObject()' (und ihren Rückgabetyp)? – stefankmitph

Antwort

1

In der Seitenaufbau ist:

enum ColorEnum 
{ 
    Red, 
    Green, 
    Blue 
}; 

Wir wissen, dass Red existiert, aber nichts über andere Farben. Also definieren wir das Enum in unserer Versammlung nur mit bekannten Werten neu.

enum KnownColorEnum // in your assembly 
{ 
    Red 
}; 

Deshalb können wir Parsing durchfahren:

public static KnownColorEnum? GetKnownColor(object value) 
{ 
    KnownColorEnum color; 

    if (value != null && Enum.TryParse<KnownColorEnum>(value.ToString(), out color)) 
    { return color; } 

    return null; 
} 

Beispiele:

// thatObject.Color == ColorEnum.Red 
// or 
// thatObject.Color == "Red" 
if (GetKnowColor(thatObject.Color) == KnownColorEnum.Red) // true 
{ } 

// thatObject.Color == ColorEnum.Blue 
if (GetKnowColor(thatObject.Color) == KnownColorEnum.Red) // false 
{ } 
+0

Dies verwendet 'ToString()' auch. Wie ist das besser als nur das String-Literal zu vergleichen? – sharptooth

+0

Es ist nur besser, weil Typen verwendet werden. Sie können keine Integer-Repräsentationen verwenden, da ColorEnum ebenfalls geändert werden kann. Es ist also nur eine Möglichkeit, den String-Vergleich zu verwenden. –

+0

Ja, es verwendet 'TryParse()' und extrahiert eine parallele Enumeration. Ist das der Unterschied? – sharptooth

2

Wie über die Color-Eigenschaft auf Ihre Enum ersten

if ((ColorEnum) Enum.Parse(typeof (ColorEnum), thatObject.Color.ToString()) == ColorEnum.Red) 
{ 
    // do something 
} 
+0

Ich habe nicht den Verweis auf die Assembly, sonst würde ich einfach auf ColorEnum umstellen und vergleichen. – sharptooth

+0

Aber Sie können enum in Ihrer Versammlung neu definieren und es verwenden :) –

+0

@YohDeadfall Nein, kann ich nicht, weil diese zwei verschiedene enums sein werden. – sharptooth

0

Eine mögliche (unorthodox) Art und Weise Parsen ist: Zwingen Sie Ihr dynamisches Objekt (was auch immer Objekt ist) ein ExpandoObject zu sein (mit dieser Erweiterung Methode):

public static dynamic ToDynamic(this object value) 
    { 
     IDictionary<string, object> expando = new ExpandoObject(); 

     foreach (PropertyDescriptor property in TypeDescriptor.GetProperties(value.GetType())) 
      expando.Add(property.Name, property.GetValue(value)); 

     return expando as ExpandoObject; 
    } 

Konvertieren Sie Ihre obtainedObject:

var obtainedObject = (object)obtainThatObject(); 
var myexpando = obtainedObject.ToDynamic(); // now you have an ExpandoObject 

So können Sie erhalten Sie die Eigenschaften in einem IDictionary

IDictionary<string, object> dictionary= (IDictionary<string, object>) myexpando; 
if(dictionary.ContainsKey("Color")) 
{ 
    var myValue = dictionary["Color"]; 
    string color = myValue.ToString(); 
    if(color == "Green") 
    { 
     // blah 
    } 
} 

gehen diese Weise müssen Sie sich nicht, was Objekt, das es ...

+1

Wow !!! Wie ist das besser als nur '.Color.ToString() ==" Grün "'? – sharptooth

+0

Do not do 'if (dictionary.ContainsKey (" Farbe ")) {var myValue = dictionary [" Color "];'; Verwenden Sie stattdessen ['Dictionary .TryGetValue'] (https://msdn.microsoft.com/en-us/library/bb347013 (v = vs.110) .aspx). – BCdotWEB