[.NET] Serialization d'interfaces

Heyo les geeks, j’ai besoin d’un petit peu d’aide…

J’ai une jolie classe qui possède une collection d’interfaces IPouet. Pour ça j’ai une classe PouetCollection qui implémente ICollection. Manque de bol, comme je veux sérializer (woo hooo vive les anglicismes) ma classe de base, ça chie, évidemment, puisque le XmlSerializer tombe sur un paquet d’interfaces IPouet et il sait pas quoi en faire…

Je suis un moyen newbie en C#, mais un gros newbie en serialization XML, donc je cherche quelques infos sur le net, mais rien de bien transcendant sur ce genre de cas…

J’ai fait les trucs suivants:[ol]
[li]Il parait que pour les collections il faut un indexer public pour que ça serialize bien. Je l’ai fait, mais bon, ça a pas grand chose à voir avec le problème principal.[/li][li]J’ai essayé, histoire de voir si ça passe, de foutre en gros bourrin des attributs “XmlInclude” un peu partout, pour dire au XmlSerializer les types concrets qu’il trouvera derrière IPouet, mais rien de bien concluant.[/li][li]J’ai essayé de faire hériter IPouet de IXmlSerializable. Les types concrets, du coup, font eux-même leur sérialization (enfin en recréant un XmlSerializer sur eux-même, mais bon). L’erreur change, mais ça marche toujours pas (il cherche un constructeur par défaut sur l’interface IPouet! C’est con non?)[/li][/ol]J’ai vaguement trouvé quelques autres pistes, mais je trouve que c’est assez moyen:[ol]
[li]Mettre un “XmlIgnore” sur la collection d’interfaces, et exposer cette collection en tant que collection d’objets concrets protégée… euuuh mouais bof.[/li][li]Remplacer l’interface IPouet par une classe abstraite, genre AbstractPouet. Moyen aussi.[/li][/ol]Des idees? Des commentaires? Des insultes vis à vis de mes architectures de classes idiotes?

(Note: vu que je n’ai pas encore croisé de collection d’interfaces dans le framework, je me dis que c’est peut etre quelque chose qui ne se fait pas vraiment en fait? Apparemment, ils font plutot des collections de classes abstraites, genre la collection de Control dans WinForms)

Ya un truc idiot que t’as pas essayé de faire: [Serializable] au début de ton interface?

Ca veut dire que toutes les classes qui implémentent ton interface devront aussi porter l’attribut [Serializable] (ainsi que tous les membres de ta classe). Note c’est pas parce que ca porte l’attribut Serializable que ca tu dois forcément utiliser un sérialiseur binaire, je pense que ca doit fonctionner aussi avec un sérialiseur XML.

Note: c’est comme ca que je fais pour sérialiser mes packets de données pour transmettre sur un réseau (classe abstraite Packet en [Serializable], toutes les classes filles idem… donc peut être que ca marche aussi avec les interfaces).

Vous pouvez aussi me traiter de goret si vous en avez envie :P.

En plus de l’attribut Serializable, tu as essayé de rajouter ton interface dans l’appel du XMLSerializer genre comme ca :

public string Serialiser() { TextWriter writer=null; try { XmlSerializer serializer=new XmlSerializer(typeof(PouetCollection),new Type[] {typeof(IPouet)}); writer=new StringWriter(); serializer.Serialize(writer,this); return writer.ToString(); } finally { if (writer!=null) writer.Close(); } }

Mais aucune idée de si ca marche.

Remarque :
Une question qui m’interpelle.
Les interfaces servent uniquement à déclarer des méthodes que les classes implémentant l’interface devra définir. Non?
Donc tu as du faire des classes Pouet1, Pouet2 qui dérivent toutes de IPouet. Non ?
Si oui essaye de rajouter dans le tableau de type, de mon exemple, les type Pouet1 et Pouet2. En leur ajoutant l’attribut Serializable.
Mais je suis peut etre un gros nOobs, donc vous avez le droit de me jeter des pierres

La Sérialization XML ne fonctionne pas à priori sur des interfaces, mais il est censé regarder si les classes l’implémentant sont XmlSerializable.
Sinon, tu peux effectivement placer l’attribut [Serailizable] un peu partout et faire de la sérialization SOAP/XML (c’est pas la même méthode, et avec celle là, tu n’as pas à avoir de propriétés publiques en lecture/ecriture). Regardes dans le namespace System.Runtime.Serualization.Formatters.SOAPFormatter ou un truc dans le genre ^^.

L’attribut “Serializable” ne peut être mis sur des interfaces (il ne peut être mis que sur des classes, des structures, des enums, et des delegates).

Fournir les types concrets implémentant l’interface (Pouet1, Pouet2, etc.) au sérialiseur ne l’aide pas. Il sort une exception lorsqu’il rencontre l’interface (IPouet) en tant que membre d’une autre classe. Le fait de savoir ce qu’il trouvera derrière cette interface ne change rien à l’affaire. Mettre “Serializable” sur toutes les classes implémentant IPouet ne change rien non plus.

De toutes façons, le message d’erreur est assez explicite: “Can’t serialize member Gnagna of type IPouet because it is an interface”. Si on pouvait corriger ça à coups d’attributs, je me dis qu’il le dirait dans le message, car il le dit, par exemple, dans le cas d’une classe abstraite, en indiquant qu’il faut rajouter des attributs “XmlInclude” pour lui donner les types concrets qu’il trouvera.

Bref, je pense qu’on ne peut tout simplement pas sérializer une classe contenant des membres de type interface. Je ne vois pas trop la différence avec un membre de type abstrait, mais bon. Du coup, j’ai changé mon design, et remplacé 2 de mes interfaces par des classes de base abstraites.

Simple: une interface n’existe “pas”: c’est un set de règles à respecter et qui sert surtout a garder une compatibilité. Par exemple un type qui programme des plugins va exposer une interface au public, a lui de se servir des fonctions de l’interface pour faire ce qu’il souhaite.

Si un jour un développeur de plugin omet une fonction qui est dictée par l’interface, la le compilo gueulera, parce que les règles n’ont pas été respectées.

Les interfaces sont donc un outil pour aider a coder rigoureusement.

D’un autre coté, la classe abstraite implémente une partie d’un code (certaines fonctions, propriétés) tout en demandant aux spécialisations d’implémenter les méthodes abstraites définies dans la classe parente; cela correspond, si tu veux a une combinaison d’interface (pour les méthodes/propriétés abstraites) + classe (pour les méthodes/propriétés définies dans la classe abstraite).

Il y a donc bien du code associé, et c’est donc pourquoi une classe abstraite peut être sérialisée.

Enfin, c’est clair dans ma tête, c’est un peu dur à expliquer… si GloP pouvait passer pour mieux expliquer…

Note: en ce qui concerne les interfaces, j’ai vu des types complètement dingues coder toute leur applis à travers des interfaces d’abord (pour avoir le squelette de l’application, même si elle ne faisait rien) et ensuite coder l’intérieur des classes en remplacant au fur et a mesure les interfaces par des classes… je sais pas si c’est une bonne méthode?

Pour le codeur d’API (genre moi) classe abstraite rulez. Sinon lordabdul connait bien la diff class abstraite/interface, c’est pas trop ca son probleme :stuck_out_tongue:

Bah je pense que mon background de codeur C++ doit m’enduire d’erreur (wouah c’est dégueu) passkeu en C++, y’a aucune différence entre une interface et une classe abstraite (à part le voeux pieux de ne mettre aucune implémentation dedans, et de mettre un « I » devant le nom). Alors qu’en C#, y’a un mot clé fait pour, et c’est donc probablement implémenté différemment dans le CLR. Mais bon bref, tout va bien maintenant, je sérialize comme un fou, c’est la fête.