2012-04-18 18 views
6

Ist es möglich, einen Dictionary<string, Anything> zu einem konsistenten mittleren generischen Typ zu konvertieren? Also wäre ich in der Lage, <string, string>, <string, bool>, <string, int>, <string, anything> alle auf die gleiche Art von Wörterbuch zu werfen?C# Cast Dictionary <String, AnyType> zu Dictionary <String, Objekt> (Involving Reflection)

ich an einem Projekt arbeite, die schwere Reflexion verwendet, und ich brauche Dictionary-Typen als solche verarbeiten zu können:

FieldInfo field = this.GetType().GetField(fieldName); 
Dictionary<string, Object> dict = (Dictionary<string, Object>)field.GetValue(this); 

Der obige Code ist das, was zur Zeit ich habe, und das Programm nicht immer auf dem cast von field.GetValue auf das generische Dictionary<string, Object>.

Gibt es eine Möglichkeit, dies zu tun? Oder sollte ich einfach eine andere Möglichkeit finden, diese Wörterbücher zu verarbeiten?

Jede Hilfe würde sehr geschätzt werden.

Antwort

8

nach AakashM's answer, die Besetzung scheint nicht Ball zu spielen. Sie können umgehen, indem Sie eine kleine Hilfsmethode though:

Die Ente Eingabe in foreach ist in diesem Fall praktisch.

+0

Das hat wie ein Zauber funktioniert, Danke AakashM und Gibsnag. Das gab mir eine Weile Probleme. –

+2

Es gibt keine Notwendigkeit für eine spezielle CastDict-Methode, Sie können einfach den normalen Cast () LINQ-Operator verwenden. –

5

Hilft Ihnen das?

Dictionary<a, b> output = 
    input.ToDictionary(item => item.Key, item => (SomeType)item.Value); 
+0

Ich kann die ToDictionary-Methode nicht wirklich aufrufen, da ich Reflektion verwende. Ich könnte vielleicht mehr Reflektion verwenden, um zur ToDictionary-Methode zu gelangen, aber dann wäre ich mir nicht sicher, wie ich diese Parameter in diese Methode einbringen könnte. –

8

Auch wenn Sie eine Möglichkeit, dies auszudrücken finden könnten, wäre es die falsche Sache zu tun - es ist nicht wahr, dass ein Dictionary<string, bool> ist ein Dictionary<string, object>, so dass wir definitiv nicht wollen, zu werfen . Bedenken Sie, dass wenn wir könnte werfen, könnten wir versuchen und setzen Sie eine string in als ein Wert, der offensichtlich nicht passt!

Was wir tun können, ist jedoch, zu gieße die nicht generische IDictionary (die alle Dictionary<,> s implementieren), dann verwenden eine neueDictionary<string, object> mit den gleichen Werten zu konstruieren:

FieldInfo field = this.GetType().GetField(fieldName); 
IDictionary dictionary = (IDictionary)field.GetValue(this); 
Dictionary<string, object> newDictionary = 
    dictionary 
    .Cast<dynamic>() 
    .ToDictionary(entry => (string)entry.Key, 
        entry => entry.Value); 

(beachten Sie, dass Sie nicht .Cast<DictionaryEntry> hier für the reasons discussed here verwenden können. Wenn Sie Pre-C# 4, sind und so haben keine dynamic, müssen Sie die Aufzählung manuell tun, wie Gibsnag's answer does)

+0

Ich erhalte immer noch einen Fehler "Angegebener Cast ist nicht gültig" mit diesem Code. Irgendwelche Ideen? –

+0

Was ist der tatsächliche Typ des Objekts, das 'field.GetValue()' zurückgibt? – AakashM

+0

Nun, ich weiß in der Tat, dass es versucht, ein 'Dictionary ' zu bekommen, aber das ist nur, weil es mein erster Testfall ist. Während der Laufzeit 'Console.WriteLine (field.GetValue (this) .GetType(). Name);' druckt "Dictionary'2" aus. Edit: Ich habe gerade 'Console.WriteLine (field.GetValue (this)));' und habe 'System.Collections.Generic.Dictionary'2 [System.String, System.String]' –

0

Ja, es ist möglich, die FieldInfo-Dictionary wie unten

Dies ist ein Beispiel zu werfen, ich habe in meinem Code verwendet

Dictionary<string, string> 
       GetTheDict = FilesAndPaths.GetType() 
          .GetFields() 
          .Where(f => f.Name.Equals(pLoadFile)) 
          .Select(f => (Dictionary<string, string>)f.GetValue(FilesAndPaths)) 
          .Single(); 
0

Überlegen Sie, ob zum Gießen und von object wirklich notwendig ist. Ich begann diesen Weg und stolperte über diesen Artikel, bevor ich realisierte, dass ich das erreichen konnte, was ich durch Generika und nicht durch Konvertierung brauchte. Beispielsweise;

class DictionaryUtils<T> 
{ 
    public static T ValueOrDefault(IDictionary<string, T> dictionary, string key) 
    { 
     return dictionary.ContainsKey(key) ? dictionary[key] : default(T); 
    } 
} 

Dieses Stück Code ist viel sauberer und wird in anderen Antworten gezeigt schneller als der entsprechende Conversion-Code sein.

Verwandte Themen