SAGA 3: Sérialisation XML
Par amethyste le Aoû 17, 2008 | Dans focus | Réagir »
Cette semaine nous allons sérialiser de différentes manières des collections.
On commence par créer la classe Continent suivante:
public sealed class Continent { #region Constructeurs /// <summary> /// Constructeur par défaut /// </summary> public Continent() { Pays = new List<Pays>(); } #endregion public List<Pays> Pays; }
La sérialisation faite nous donne quelquechose qui ressemble à:
<?xml version="1.0" encoding="utf-8"?> <Continent> <Pays> <Pays capitale="Paris"> <nom>France</nom> </Pays> <Pays capitale="Berlin"> <nom>Allemagne</nom> </Pays> </Pays> </Continent>
Transformons la balise <Continent> avec des minuscules grâce à l'attribut XmlRoot.
[XmlRoot("continent")] public sealed class Continent { }
Je vous laisse découvrit le (très) prévisible résultat.
Profitons en pour découvrir un très méconnu comportement de XmlElement. Effectuons le remplacement suivant:
[XmlElement("pays")] public List<Pays> Pays;
On obtient alors:
<continent> <pays capitale="Paris"> <nom>France</nom> </pays> <pays capitale="Berlin"> <nom>Allemagne</nom> </pays> </continent>;
Un niveau disparaît. Pour le conserver on doit utiliser d'autres attributs:
[XmlArray("nation")] [XmlArrayItem("pays")] public List<Pays> Pays;
On obtient:
<continent> <nation> <pays capitale="Paris"> <nom>France</nom> </pays> <pays capitale="Berlin"> <nom>Allemagne</nom> </pays> </nation> </continent>;
Pour l'instant nous nous sommes contenté de situations pour laquelle le type des membres de la classe sérialisée est connu. Mais dans la réalité ce n'est pas toujours possible.
Complétons par exemple la classe Pays avec la propriété suivante:
public ResourceEnEau Eau;
ResourceEnEau est la classe abstraite suivante:
public abstract class ResourceEnEau { public string Nom; }
elle admet deux dérivés:
public class Lac : ResourceEnEau { public int Surface; } public class Riviere : ResourceEnEau { public int Longueur; }
Pas les même classes, pas les mêmes membres. On vérifie facilement qu'en l'état la sérialisation ne fonctionne pas. La raison est assez facile à comprendre. Lors de la déclaration et l'instanciation de XmlSerializer, on fournit le type de données qui sera sérialisé:
XmlSerializer serialiseur = new XmlSerializer(typeof(Pays));
En interne le compilateur va créer une classe spécialisée dans la sérialisation de Pays. La classe n'est pas créée à la volée, ce qui assure des performances meilleures.
Seulement dans notre nouvelle situation on rencontre une classe abstraite, on aurait même pu avoir une interface. Le compilateur ignore alors tout de la classe réelle et ne pourra pas terminer son travail... à moins d'être aidé!
Il existe deux approches possibles.
Si la liste des types possible est connue et ne varie pas, les attributs peuvent venir à notre secours:
[XmlElement(Type=typeof(Lac))] [XmlElement(Type=typeof(Riviere))] public ResourceEnEau Eau;
Si on ne peut pas accéder au source des classes ou si la liste des types varie et doit donc être obtenue par exemple par réflexion:
Type[] Types = new Type[] {typeof(Lac),typeof(Riviere) }; XmlSerializer serialiseur = new XmlSerializer(typeof(Continent),Types);
Dans les deux cas on obtient quelque chose de similaire (il y a une légère différence dans le résultat):
<continent> <nation> <pays capitale="Paris"> <Riviere> <Nom>Seine</Nom> <Longueur>776</Longueur> </Riviere> <nom>France</nom> </pays> <pays capitale="Berlin"> <Lac> <Nom>Constance</Nom> <Surface>538</Surface> </Lac> <nom>Allemagne</nom> </pays> </nation> </continent>
Suite la semaine prochaine pour voir d'autres cas de figure.
Notes d'ailleurs
Une des premières photographie prise par Neil Armstrong lors de son arrivée sur la Lune fut le pied du LEM. Ce cliché est devenu une tradition à la NASA et se trouve être une des premières images prises par une sonde qui se pose sur un autre sol. On l'appelle depuis le "cliché Armstrong".
Ce cliché a une utilité pratique bien sur, il permet de vérifier que l'appareil s'est posé sur un terrain stable.
Aucun commentaire pour le moment
Laisser un commentaire
| « SAGA 4: sérialisation XML | SAGA 2: La sérialisation XML » |