2010-12-13 6 views
4

Je suis confronté à un problème de réflexion dans C# et je ne trouve pas la réponse.Réflexion sur les types génériques hérités

J'ai une classe qui hérite d'un type générique, et j'essaie de récupérer le type de T de cette classe, mais il s'avère que je ne peux pas!

Voici un exemple:

class Products : List<Product> 
{} 

Le problème est que lors de l'exécution, je ne sais pas le type de T. J'ai donc essayé d'obtenir le type comme ceci:

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

Il n'a pas fonctionné.

Voici ma méthode:

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

L'idée est de lire un fichier XML et de le transformer en un objet:

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

dans ce cas, le nœud produits seraient ma collection qui hérite de la liste

des idées sur la façon de faire cela?

gars TKS

Répondre

6

La classe Products n'est pas générique, donc GetGenericArguments ne retourne rien.

Vous devez obtenir les arguments génériques du type de base, comme ceci:

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

Cependant, ce n'est pas élastique; Si un type de base intermédiaire non générique est introduit, il échouera. À la place, vous devriez trouver le paramètre type de l'implémentation IList<T>.

Par exemple:

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

merci SLaks! ça a marché! –

1

Si vous êtes juste à essayer de comprendre ce que le type d'un IList est, vous devez utiliser quelque chose comme ceci:

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

Voici comment l'utiliserait dans le code:

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); 
    } 
} 
Questions connexes