2009-10-11 10 views
1

J'ai un tableau d'éléments que j'ai besoin de sérialiser en utilisant XmlSerializer. Le problème que j'ai est que j'ai 2 classes dérivées, et les sérialiser pour qu'elles aient un nom d'élément de la base commune, ne semble pas fonctionner.Sérialisation XML des classes dérivées

Alors, voici comment le XML devrait ressembler à:

<Root> 
    <Base> foo </Base> 
</Root> 

Au lieu de cela, je reçois

<Root> 
    <Derived1> foo </Derived1> 
</Root> 

Le code pour le tableau des éléments que je suis sérialisation est

private object[] m_nodes; 

[System.Xml.Serialization.XmlElementAttribute("Base", typeof(Derived1)] 
[System.Xml.Serialization.XmlElementAttribute("Base", typeof(Derived2)] 

public object[] Nodes 
{ 
    get 
    { 
     return this.m_nodes; 
    } 
    set 
    { 
     this.m_nodes = value; 
    } 
} 

Avec le code ci-dessus, j'obtiens qu'il y a une erreur de réflexion avec les nœuds. Si je change "Base" dans les deux XmlEelementAttributes à "Derived1" et Derived2" , cela fonctionne, mais le nom de l'élément est incorrect.

[System.Xml.Serialization.XmlInclude(typeof(Derived1))] 
public abstract class Base 
{ 
    public Base() 
    { 

    } 
} 



[System.SerializableAttribute()] 
[System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true)] 
public class Derived1: Base 
{ 
    public Derived1() 
    { 

    } 
} 

Toute aide est grandement appréciée. Merci beaucoup.

Répondre

5

Le XML Comme la sérialisation inclut à la fois les routines de sérialisation et de désérialisation, si vous avez réussi à le faire, le sérialiseur ne pourra pas déterminer le type à utiliser lors de la désérialisation de la structure XML résultante. utiliser un sérialiseur/désérialiseur personnalisé à l'aide des classes XmlWriter et XmlReader

1

La réponse de David est correcte. Cela n'est pas possible avec XmlSerialization nu car il ne peut pas déterminer laquelle des classes dérivées doit être instanciée lors de la désérialisation, à partir du contenu de l'élément XML.

S'il est possible d'utiliser deux noms différents, cela fonctionnera. Ils n'ont pas besoin d'être le même nom que les classes dérivées, il suffit de donner à XmlSerialization un indice pour déterminer lequel est quoi.

sérialisation personnalisée en utilisant XmlReader/Writer est toujours possible, mais il est plus de temps que la simple XmlSerialization (surtout si vous n'êtes pas un toxicomane XML expérimenté!)

Ce que je fais dans ce cas est de créer un hiérarchie intermédiaire de classes et écrire des conversions simples dans le code. Ainsi, les objets d'origine sont d'abord convertis en une structure intermédiaire qui peut être manipulée par la XmlSerialization. Par exemple, dans votre cas, vous pouvez créer une classe analogue à Base (je l'appelle BaseSerializable), et remplir les données de Derived1 et Derived2 dans celui-ci. Le BaseSerializable peut être géré par XmlSerialization. Lors de la désérialisation, vous obtenez une BaseSerializable à partir de XmlSerialization, puis déterminez (en utilisant le contenu des champs/propriétés) celle des classes Derived1/Derived2 qui doit être instanciée. Donc, en pratique, vous codez une très petite partie de la sérialisation avec votre code personnalisé et laissez le reste à la bibliothèque XmlSerialization.

+0

Merci. La vôtre et les réponses de David ont du sens maintenant que je les considère du point de vue de la nécessité de les désérialiser aussi.Je pense que j'avais supposé qu'il y avait un moyen de spécifier cela depuis quelque attribut = "Derived1" dans le XML, que je pourrais dire manuellement quel objet créer. – mfanto

Questions connexes