2015-03-04 10 views
6

Supponiamo che io so che la proprietà Color di un oggetto restituisce un'enumerazione che assomiglia a questo:Come faccio a verificare la proprietà enum quando la proprietà è ottenuta dalla dinamica in C#?

enum ColorEnum { 
    Red, 
    Green, 
    Blue 
}; 

e voglio verificare che un oggetto specifico di tipo sconosciuto (che io sappia ha Color proprietà) ha Color set a Red. Questo è quello che vorrei fare se sapevo che il tipo di oggetto:

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

Il problema è che non ho un riferimento per l'assemblea con ColorEnum e non so il tipo di oggetto.

Così, invece ho la seguente configurazione:

dynamic thatObject = obtainThatObject(); 

e non posso lanciare perché io non conosco il tipo di oggetto (e il tipo enum). Come dovrei controllare lo Color?

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

funziona, ma sembra che i peggiori esempi di codice cargo cult che ho visto in "The Daily WTF".

Come si esegue il controllo correttamente?

+0

Sai tutti i possibili valori del tipo enum nel montaggio laterale e le loro rappresentazioni numeriche? –

+0

@YohDeadfall Preferisco non fare affidamento su questo - nessuno sa cosa cambi lì. – sharptooth

+0

hai influenza sul 'getThatObject()' (e il suo tipo di ritorno)? – stefankmitph

risposta

1

Nell'assemblea lato:

enum ColorEnum 
{ 
    Red, 
    Green, 
    Blue 
}; 

Sappiamo che Red esiste, ma nulla sugli altri colori. Quindi ridefiniamo l'enum nel nostro assieme solo con valori noti.

enum KnownColorEnum // in your assembly 
{ 
    Red 
}; 

Quindi possiamo eseguire l'analisi:

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

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

    return null; 
} 

Esempi:

// 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

Questo usa anche 'ToString()'. Com'è meglio di un semplice confronto tra la stringa letterale? – sharptooth

+0

È meglio solo perché utilizza i tipi. Non è possibile utilizzare le rappresentazioni dei numeri interi perché ColorEnum può essere modificato e anche i valori sottostanti. Quindi solo un modo è utilizzare il coparison di stringhe. –

+0

Sì, utilizza 'TryParse()' ed estrae un enum parallelo. È tutta questa differenza? – sharptooth

2

ne dite di analisi proprietà di colore al vostro enum prima

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

Non ho il riferimento all'assemblaggio, altrimenti mi limiterei a trasmettere a ColorEnum e confrontare. – sharptooth

+0

Ma puoi ridefinire enum nel tuo assembly e usarlo :) –

+0

@YohDeadfall No, non posso, perché saranno due enumerazioni diverse. – sharptooth

0

Un modo possibile (non ortodosso) è: Forzare il vostro oggetto dinamico (qualunque oggetto che sia) di essere un ExpandoObject (con questo metodo di estensione):

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

Convertire tua obtainedObject:

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

in modo da poter ottenere le proprietà in un 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 
    } 
} 

andare in questo modo non c'è bisogno di prendersi cura ciò che è oggetto ...

+1

Wow !!! Com'è meglio di '.Color.ToString() ==" Verde "'? – sharptooth

+0

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

Problemi correlati