OVH Cloud OVH Cloud

Sérialisation de liste hétérogène

3 réponses
Avatar
remi_inconnu
Salut,

J'aimerais s=E9rialiser une liste d'objets de diff=E9rents types
h=E9ritant d'une m=EAme classe.
Malheureusement j'ai l'erreur suivante lors de l'ex=E9cution de
"Serialize" :
InvalidOperationException
Erreur lors de la g=E9n=E9ration du document XML.

Existe t'il un moyen qui fonctionne pour s=E9rialiser une telle liste ?.

Merci.

// Code source
using System;
using System.Collections.Generic;
using System.Text;
using System.Xml.Serialization;
using System.IO;


namespace Serialisation
{
public abstract class MonInterface
{
public abstract void action();
}
[Serializable]
public class MaClasse1 : MonInterface
{
public int m_entier;
public string m_chaine;
public MaClasse1() { m_entier =3D 0; m_chaine =3D ""; }
public override void action() { }
}
[Serializable]
public class MaClasse2 : MonInterface
{
public int m_entier;
public string m_chaine;
public MaClasse2() { m_entier =3D 0; m_chaine =3D ""; }
public override void action() { }
}

[Serializable]
public class MaListe : List<MonInterface>
{
}

class Program
{
static void Main(string[] args)
{
List<MonInterface> maListe =3D new List<MonInterface>();
maListe.Add(new MaClasse1());
maListe.Add(new MaClasse2());
StreamWriter stream =3D new StreamWriter("Z:\\toto.xml");
XmlSerializer serializer =3D new
XmlSerializer(typeof(List<MonInterface>));
serializer.Serialize(stream, maListe);
stream.Close();
}
}
}

3 réponses

Avatar
Olivier
Bonjour,

L'erreur doit être qu'il cherche a déserialiser des objets
MonInterface alors qu'ils sont du type MaClasse1 et MaClasse2.

Pour résoudre le problème tu peux implémenter l'interface
IXmlSerializable dans tes classes.

Ou tu peux externaliser tes données (m_entier et m_chaine) dans une
autre classe. Et c'est cette classe que tu sérialisera.
En gros ca donnerait ca :
public class MaClasse1 : MonInterface
{
public MesDonnees m_data;
public MaClasse1() { m_data.m_entier = 0; m_data.m_chaine =
""; }
public override void action() { }
}
class MesDonnees
{
public int m_entier;
public string m_chaine;
}
class Program
{
static void Main(string[] args)
{
List<MesDonnees> maListe = new List<MesDonnees>();
maListe.Add(new MaClasse1().m_data);
maListe.Add(new MaClasse2().m_data);
StreamWriter stream = new StreamWriter("Z:toto.xml");
XmlSerializer serializer = new
XmlSerializer(typeof(List<MesDonnees>));
serializer.Serialize(stream, maListe);
stream.Close();
}
}

On 23 jan, 10:21, wrote:
Salut,

J'aimerais sérialiser une liste d'objets de différents types
héritant d'une même classe.
Malheureusement j'ai l'erreur suivante lors de l'exécution de
"Serialize" :
InvalidOperationException
Erreur lors de la génération du document XML.

Existe t'il un moyen qui fonctionne pour sérialiser une telle liste ?.

Merci.

// Code source
using System;
using System.Collections.Generic;
using System.Text;
using System.Xml.Serialization;
using System.IO;

namespace Serialisation
{
public abstract class MonInterface
{
public abstract void action();
}
[Serializable]
public class MaClasse1 : MonInterface
{
public int m_entier;
public string m_chaine;
public MaClasse1() { m_entier = 0; m_chaine = ""; }
public override void action() { }
}
[Serializable]
public class MaClasse2 : MonInterface
{
public int m_entier;
public string m_chaine;
public MaClasse2() { m_entier = 0; m_chaine = ""; }
public override void action() { }
}

[Serializable]
public class MaListe : List<MonInterface>
{
}

class Program
{
static void Main(string[] args)
{
List<MonInterface> maListe = new List<MonInterface>();
maListe.Add(new MaClasse1());
maListe.Add(new MaClasse2());
StreamWriter stream = new StreamWriter("Z:toto.xml");
XmlSerializer serializer = new
XmlSerializer(typeof(List<MonInterface>));
serializer.Serialize(stream, maListe);
stream.Close();
}
}

}


Avatar
remi_inconnu
Merci pour ta réponse, j'ai résolu mon problème en
sérialisant en binaire, cela fonctionne sans faire aucune modification
dans le code, c'est dommage que la sérialisation en XML ne
marche pas directement, enfin un jour peut être, dans la version 3...
;-)

Olivier a écrit :
Bonjour,

L'erreur doit être qu'il cherche a déserialiser des objets
MonInterface alors qu'ils sont du type MaClasse1 et MaClasse2.

Pour résoudre le problème tu peux implémenter l'interface
IXmlSerializable dans tes classes.

Ou tu peux externaliser tes données (m_entier et m_chaine) dans une
autre classe. Et c'est cette classe que tu sérialisera.
En gros ca donnerait ca :
public class MaClasse1 : MonInterface
{
public MesDonnees m_data;
public MaClasse1() { m_data.m_entier = 0; m_data.m_chaine =
""; }
public override void action() { }
}
class MesDonnees
{
public int m_entier;
public string m_chaine;
}
class Program
{
static void Main(string[] args)
{
List<MesDonnees> maListe = new List<MesDonnees>();
maListe.Add(new MaClasse1().m_data);
maListe.Add(new MaClasse2().m_data);
StreamWriter stream = new StreamWriter("Z:toto.xml");
XmlSerializer serializer = new
XmlSerializer(typeof(List<MesDonnees>));
serializer.Serialize(stream, maListe);
stream.Close();
}
}

On 23 jan, 10:21, wrote:
> Salut,
>
> J'aimerais sérialiser une liste d'objets de différents types
> héritant d'une même classe.
> Malheureusement j'ai l'erreur suivante lors de l'exécution de
> "Serialize" :
> InvalidOperationException
> Erreur lors de la génération du document XML.
>
> Existe t'il un moyen qui fonctionne pour sérialiser une telle liste ?.
>
> Merci.
>
> // Code source
> using System;
> using System.Collections.Generic;
> using System.Text;
> using System.Xml.Serialization;
> using System.IO;
>
> namespace Serialisation
> {
> public abstract class MonInterface
> {
> public abstract void action();
> }
> [Serializable]
> public class MaClasse1 : MonInterface
> {
> public int m_entier;
> public string m_chaine;
> public MaClasse1() { m_entier = 0; m_chaine = ""; }
> public override void action() { }
> }
> [Serializable]
> public class MaClasse2 : MonInterface
> {
> public int m_entier;
> public string m_chaine;
> public MaClasse2() { m_entier = 0; m_chaine = ""; }
> public override void action() { }
> }
>
> [Serializable]
> public class MaListe : List<MonInterface>
> {
> }
>
> class Program
> {
> static void Main(string[] args)
> {
> List<MonInterface> maListe = new List<MonInterface>();
> maListe.Add(new MaClasse1());
> maListe.Add(new MaClasse2());
> StreamWriter stream = new StreamWriter("Z:toto.xml");
> XmlSerializer serializer = new
> XmlSerializer(typeof(List<MonInterface>));
> serializer.Serialize(stream, maListe);
> stream.Close();
> }
> }
>
> }


Avatar
fragmonster
Le mieux, comme l'a dit Olivier plus haut, c'est que chacune de tes
classes implémentent l'interface IXmlSerializable. Ca te permet de
contrôler la façon dont elles vont être sérialisées.

Tu dois juste implémenter 3 méthodes :
GetSchema() (en général je retourne null ^^)
ReadXml()
WriteXml() c'est cette méthode qui te permet de controler la façon
dont tes variables de classe doivent être sérialisées.