Utilizzo di XmlSerializer con custom collection

di Marco Leoncini, in ASP.NET 2.0, XML,

XmlSerializer permette con poche e semplici righe di codice di serializzare/deserializzare campi e proprietà pubbliche di un oggetto in/da un formato XML.
Ci possiamo imbattere però in errori inaspettati, ad esempio serializzando collezioni i cui elementi sono determinati a runtime o in presenza di vincoli di ereditarietà tra le classi molto complessi.

Un'alternativa più flessibile in questi casi è personalizzare completamente il processo di serializzazione/deserializzazione, implementando l'interfaccia IXmlSerializable.

Basta creare la collection implementando l'interfaccia IXmlSerializable:

public class RuntimeCollection : Collection<BaseClass> , IXmlSerializable
{
        public System.Xml.Schema.XmlSchema GetSchema()
        {
            return null;
        }

        public void ReadXml(System.Xml.XmlReader reader)
        {
            //mi sposto sul primo elemento della collezione
            reader.Read();
            
            //finchè non raggiungo il nodo finale della collezione
            while (reader.NodeType != System.Xml.XmlNodeType.EndElement)
            {
                //recupero l'attributo che contiene le informazioni sul tipo
                string type = reader.GetAttribute(0);

                //istanzio una nuova istanza di XmlSerializer 
                XmlSerializer serializer = new XmlSerializer(Type.GetType(type));

                //deserializzo
                BaseClass item = (BaseClass)serializer.Deserialize(reader);

                //aggiungo l'istanza alla collezione
                this.Add(item);
            }
        }

        public void WriteXml(System.Xml.XmlWriter writer)
        {
            //per ogni elemento della collezione
            foreach (BaseClass p in this)
            {
                //inizializzo una nuova istanze di XmlSerializer
                XmlSerializer serializer = new XmlSerializer(p.GetType());

                //inserisco le informazioni sul tipo
                XmlSerializerNamespaces namespaces = new XmlSerializerNamespaces();
                namespaces.Add("type", p.GetType().AssemblyQualifiedName);

                //serializzo passondo il writer da riempire
                serializer.Serialize(writer, p, namespaces);
            }
        }
 }

Il metodo WriteXml scorre la collezione e crea per ogni elemento un'istanza di XmlSerilizer con il tipo dell'oggetto corrente. In previsione del processo di deserializzazione, scriviamo queste informazioni nel file XML in modo da recuperarle quando in concomitanza con quest'ultima viene richiamato il metodo ReadXml, che dal canto suo recupera le informazioni sul tipo e inizializza una nuova istanza di XmlSerializer per ricreare gli elementi che componevano la collezione.

L'interfaccia IXmlSerializable è presente anche nelle versioni 1.x del .NET Framework, non è documentata ed è implementata solamente dalla classe DataSet.
Con la versione 2.0 viene alla luce e riceve il giusto risalto, visto l'estrema importanza di personalizzare il processo di serializzazione/deserializzazione con la classe XmlSerializer.

Commenti

Visualizza/aggiungi commenti

| Condividi su: Twitter, Facebook, LinkedIn

Per inserire un commento, devi avere un account.

Fai il login e torna a questa pagina, oppure registrati alla nostra community.

Approfondimenti

I più letti di oggi