2016-10-28 5 views
0

Also habe ich diesen Code, der rekursiv alle Eigenschaften und ihren Inhalt eines bestimmten Objekts drucken soll.Iterieren über Wörterbuch durch Reflexion erhalten

static public void PrintProperties(object obj, int indent) 
{ 
    if (obj == null) return; 
    string indentString = new string(' ', indent); 
    Type objType = obj.GetType(); 
    PropertyInfo[] properties = objType.GetProperties(); 
    foreach (PropertyInfo property in properties) 
    { 
     object propValue = property.GetValue(obj, null); 
     if (property.PropertyType.Assembly == objType.Assembly && !property.PropertyType.IsEnum) 
     { 
      Console.WriteLine("{0}{1}:", indentString, property.Name); 
      PrintProperties(propValue, indent + 2); 
     } 
     else 
     { 
      if (null != propValue) 
      { 
       Type t = propValue.GetType(); 
       //Console.WriteLine(":::::{0}:::::", propValue.GetType()); 
       bool isDict = t.IsGenericType && t.GetGenericTypeDefinition() == typeof(Dictionary<,>); 
       if (isDict) 
       { 
        Type keyType = t.GetGenericArguments()[0]; 
        Type valueType = t.GetGenericArguments()[1]; 
        foreach (KeyValuePair<keyType, valueType> kvp in (Dictionary<keyType, valueType>)propValue) 
        { 
         Console.WriteLine(string.Format("Key = {0}, Value = {1}", kvp.Key, kvp.Value)); 
        } 
       } 
      } 

      Console.WriteLine("{0}{1}: {2}", indentString, property.Name, propValue); 
     } 
    } 
} 

Es funktioniert nicht für List und Dictionary noch, ich bin in diesem Augenblick auf dem Dictionary Teil arbeiten.

Problem ist, extrahieren ich die Art des Schlüssels und Wert mit:

Type keyType = t.GetGenericArguments()[0]; 
Type valueType = t.GetGenericArguments()[1]; 

Aber dann VS2013 sagt mir, dass es ein Problem mit dieser Zeile:

foreach (KeyValuePair<keyType, valueType> kvp in (Dictionary<keyType, valueType>)propValue) 

Es sagt mir, dass Der Typ oder Namespace KeyType und valueType wurden nicht gefunden. Was fehlt mir?

Danke.

PS: .net 4.5.1

+0

'keyType' &' valueType' in Ihrem Beispiel sind Instanzen von '' aber Baumuster zur KeyValuePair 'erfordert einen Typnamen so, dass der Typ zur Laufzeit ausgewertet werden kann. Sie müssen auf das Wörterbuch mit der nicht-generischen 'Dictionary'-Klasse zugreifen und die Schlüssel- und Wertobjekte manuell umwandeln. – Howwie

+1

Mögliches Duplikat von [Wie lassen sich ganze Objekte am besten in C# ablegen?] (Http: // stackoverflow.com/questions/360277/what-is-the-best-weg-zu-dump-gesamte-objekte-zu-einem-log-in-c) –

Antwort

1

In Anrufen zu generischen Methoden müssen Sie tatsächliche Typnamen bereitstellen (oder generischen Typparameter aus Ihrer eigenen Methode Definition übergeben) - keine Instanzen von Type.

+0

So gibt es keine Möglichkeit, den Inhalt eines Wörterbuches automatisch durch extrahiert zu drucken Betrachtung? weil ich in 'propValue' den Typ des Schlüssels und des Wertes sehen kann (Beispiel:' System.Collections.Generic.Dictionary 2 [Mobile.Fonct ionComptage.Modele.IndexFournisseur, System.String] ') –

1

Grundsätzlich Ihre keyType & valueType sind Variablen vom Typ Type, die zur Laufzeit bekannt sind, so müssten Sie Reflexion verwenden, um Ihre propValue auf eine geeignete allgemeine Wörterbuch zu werfen. Sie können jedoch die Tatsache verwenden, dass Dictionary<TKey,TValue> aus Gründen der Abwärtskompatibilität die nicht generische Schnittstelle IDictionary implementiert.

So in Ihrem speziellen Fall würde es ausreichen, diese zu ersetzen:

foreach (KeyValuePair<keyType, valueType> kvp in (Dictionary<keyType, valueType>)propValue) 

mit diesem:

foreach (DictionaryEntry kvp in (IDictionary)propValue) 
1

Wie decPL angegeben, sollten Sie System.Collections.IDictionary verwenden. Sie sollten jedoch auch Ihre isDict-Logik ändern. Mit System.Type.IsAssignableFrom können Sie überprüfen, ob eine Instanz eines angegebenen Typs der aktuellen Typinstanz zugewiesen werden kann. Hier ist Code, der das Verhalten zeigt.

using System; 
using System.Collections; 
using System.Collections.Generic; 

namespace ConsoleApplication1 
{ 
    class Program 
    { 
     static void Main(string[] args) 
     { 
      Console.WriteLine("Testing System.Type.IsAssignableFrom"); 

      var propValue = new Dictionary<string, string>() { { "hello", "world" } }; 
      var t = propValue.GetType(); 
      bool isDict = typeof(IDictionary).IsAssignableFrom(t); 
      if (isDict) 
      { 
       foreach (DictionaryEntry kvp in (IDictionary)propValue) 
       { 
        Console.WriteLine(string.Format("Key = {0}, Value = {1}", kvp.Key, kvp.Value)); 
       } 
      } 

      Console.ReadLine(); 
     } 
    } 
} 

So sollte Ihre Methode so aussehen.

static public void PrintProperties(object obj, int indent) 
{ 
    if (obj == null) return; 
    string indentString = new string(' ', indent); 
    Type objType = obj.GetType(); 
    PropertyInfo[] properties = objType.GetProperties(); 
    foreach (PropertyInfo property in properties) 
    { 
     object propValue = property.GetValue(obj, null); 
     if (property.PropertyType.Assembly == objType.Assembly && !property.PropertyType.IsEnum) 
     { 
      Console.WriteLine("{0}{1}:", indentString, property.Name); 
      PrintProperties(propValue, indent + 2); 
     } 
     else 
     { 
      if (null != propValue) 
      { 
       Type t = propValue.GetType(); 
       //Console.WriteLine(":::::{0}:::::", propValue.GetType()); 
       bool isDict = typeof(IDictionary).IsAssignableFrom(t); 
       if (isDict) 
       { 
        foreach (DictionaryEntry kvp in (IDictionary)propValue) 
        { 
         Console.WriteLine(string.Format("Key = {0}, Value = {1}", kvp.Key, kvp.Value)); 
        } 
       } 
      } 

      Console.WriteLine("{0}{1}: {2}", indentString, property.Name, propValue); 
     } 
    } 
} 

Sie könnten dies jedoch auch mit der C# als Operator tun. Der as-Operator versucht, eine Umwandlung in den angegebenen Typ durchzuführen. Wenn dies nicht möglich ist, wird null zurückgegeben. Ein Beispielcode.

using System; 
using System.Collections; 
using System.Collections.Generic; 

namespace ConsoleApplication1 
{ 
    class Program 
    { 
     static void Main(string[] args) 
     { 
      Console.WriteLine("Testing System.Type.IsAssignableFrom"); 

      var propValue = new Dictionary<string, string>() { { "hello", "world" } }; 
      IDictionary asDict = propValue as IDictionary; 
      if (asDict != null) 
      { 
       foreach (DictionaryEntry kvp in (IDictionary)propValue) 
       { 
        Console.WriteLine(string.Format("Key = {0}, Value = {1}", kvp.Key, kvp.Value)); 
       } 
      } 

      Console.ReadLine(); 
     } 
    } 
} 

Und Ihre Methode.

static public void PrintProperties(object obj, int indent) 
{ 
    if (obj == null) return; 
    string indentString = new string(' ', indent); 
    Type objType = obj.GetType(); 
    PropertyInfo[] properties = objType.GetProperties(); 
    foreach (PropertyInfo property in properties) 
    { 
     object propValue = property.GetValue(obj, null); 
     if (property.PropertyType.Assembly == objType.Assembly && !property.PropertyType.IsEnum) 
     { 
      Console.WriteLine("{0}{1}:", indentString, property.Name); 
      PrintProperties(propValue, indent + 2); 
     } 
     else 
     { 
      if (null != propValue) 
      { 
       var asDict = propValue as IDictionary; 
       if (asDict != null) 
       { 
        foreach (DictionaryEntry kvp in asDict) 
        { 
         Console.WriteLine(string.Format("Key = {0}, Value = {1}", kvp.Key, kvp.Value)); 
        } 
       } 
      } 

      Console.WriteLine("{0}{1}: {2}", indentString, property.Name, propValue); 
     } 
    } 
} 
Verwandte Themen