2010-12-13 14 views
4

Ich habe ein Problem mit der Reflexion in C# und ich kann die Antwort nicht finden.Reflexion über geerbte generische Typen

Ich habe eine Klasse, die von einem generischen Typ erbt, und ich versuche, den Typ von T aus dieser Klasse abrufen, aber es stellt sich heraus, dass ich nicht kann! Hier

ist ein Beispiel:

class Products : List<Product> 
{} 

Das Problem ist, dass ich zur Laufzeit nicht wissen, welche Art von T. Also habe ich versucht, die Art, wie diese zu bekommen:

Type itemsType = destObject.GetType().GetGenericArguments()[0] 

Es hat nicht geklappt.

Hier ist meine Methode:

public static object Deserialize(Type destType, XmlNode xmlNode) 
    {   
     object destObject = Activator.CreateInstance(destType); 

     foreach (PropertyInfo property in destType.GetProperties()) 
      foreach (object att in property.GetCustomAttributes(false)) 
       if (att is XmlAttributeAttribute) 
        property.SetValue(destObject, xmlNode.Attributes[property.Name].Value, null); 
       else if (att is XmlNodeAttribute) 
       { 
        object retObject = Deserialize(property.PropertyType, xmlNode.Nodes[property.Name]); 
        property.SetValue(destObject, retObject, null); 
       } 

     if (destObject is IList) 
     { 
      Type itemsType = destObject.GetType().GetGenericArguments()[0]; 
      foreach (XmlNode xmlChildNode in xmlNode.Nodes) 
      { 
       object retObject = Deserialize(itemsType, xmlNode); 
       ((IList)destObject).Add(retObject); 
      } 
     } 

     return destObject; 
    }   

Die Idee ist, eine XML-Datei und wandeln es in ein Objekt zu lesen:

<?xml version="1.0" encoding="UTF-8" standalone="yes"?> 
<SETTINGS> 
    <PRODUCTS> 
    <PRODUCT NAME="ANY" VERSION="ANY" ISCURRENT="TRUE" /> 
    <PRODUCT NAME="TEST1" VERSION="ANY" ISCURRENT="FALSE" /> 
    <PRODUCT NAME="TEST2" VERSION="ANY" ISCURRENT="FALSE" /> 
    </PRODUCTS> 
    <DISTRIBUTIONS> 
    <DISTRIBUTION NAME="5.32.22" /> 
    </DISTRIBUTIONS> 
</SETTINGS> 

in diesem Fall sind die Knoten PRODUCTS würde meine Sammlung sein, die erbt aus der Liste

irgendwelche Ideen, wie man das macht?

tks Jungs

Antwort

6

Die Products Klasse ist nicht generisch, so GetGenericArguments nichts zurückkommt.

Sie müssen die allgemeinen Argumente des Basistyps zu erhalten, wie folgt aus:

Type itemType = destObject.GetType().BaseType.GetGenericArguments()[0]; 

Dies ist jedoch nicht elastisch; Wenn ein nichtgenerischer Basistyp eingeführt wird, schlägt er fehl.
Stattdessen sollten Sie den Typ Parameter der IList<T> Implementierung finden.

Zum Beispiel:

Type itemsType = destType.GetInterface(typeof(IList<>).Name).GetGenericArguments()[0]; Sie

Hier ist, wie:

Type listImplementation = destObject.GetType().GetInterface(typeof(IList<>).Name); 
if (listImplementation != null) { 
    Type itemType = listImplementation.GetGenericArguments()[0]; 
    ... 
} 
+0

danke SLaks! es funktionierte! –

1

Wenn Sie nur versuchen, herauszufinden, was der Typ eines IList ist, Sie so etwas wie diese verwenden sollten würde es in Code verwenden:

var interface = destType.GetInterface(typeof(IList<>).Name); 
var destList = destObject as IList; 
// make sure that the destination is both IList and IList<T> 
if (interface != null && destList != null) 
{ 
    Type itemsType = interface.GetGenericArguments()[0]; 
    foreach (XmlNode xmlChildNode in xmlNode.Nodes) 
    { 
     object retObject = Deserialize(itemsType, xmlNode); 
     destList.Add(retObject); 
    } 
}