2011-01-11 3 views
9

Je suis en train d'exécuter un code similaire à ceci:interfaces Sérialisation

using System; 
using System.Collections.Generic; 
using System.IO; 
using System.Xml.Serialization; 

namespace ConsoleApplication1 
{ 
    [Serializable] 
    [XmlInclude(typeof(List<Class2>))] 
    public class Class1 
    { 
     private IList<Class2> myArray; 

     public IList<Class2> MyArray 
     { 
      get { return myArray; } 
      set { myArray = value; } 
     } 

    } 

    public class Class2 
    { 
     private int myVar; 

     public int MyProperty 
     { 
      get { return myVar; } 
      set { myVar = value; } 
     } 

    } 

    class Program 
    { 
     static void Main(string[] args) 
     { 
      XmlSerializer ser = new XmlSerializer(typeof(Class1), new Type[] { typeof(List<Class2>) }); 
      FileStream stream = File.OpenWrite("Data.xml"); 
      ser.Serialize(stream, new List<Class1>()); 
      stream.Close(); 
     } 
    } 
} 

Quelqu'un peut-il me expliquer ce que je fais mal?

Je reçois un:

Impossible de sérialiser membre .. MonTableau ... parce qu'il est une interface.

Est-ce que XmlInclude ne devrait pas résoudre cela?

+0

qui a dit quoi que ce soit au sujet de la désérialisation ...? –

Répondre

13

Non. Vous ne pouvez pas sérialiser une interface. Déjà. Ça vient de te le dire.

Une interface n'est rien de plus qu'une description d'un ensemble de comportements. Il ne dit rien sur le contenu d'une instance. En particulier, bien qu'une instance d'une classe implémentant une interface doive implémenter tous ses membres, elle aura certainement ses propres propriétés qui doivent être sérialisées.

Comment serait-il désérialisé?

Quelle classe serait utilisée pour désérialiser l'interface de l'autre côté?

+0

Des solutions de contournement? – Shahar

+3

@Shahar: oui. Ne fais pas ça. Utilisez un type concret, pas une interface. –

+1

Comment serait-il désérialisé? En tant qu'instance de la classe qui a été sérialisée, tout comme la liste . Quelle classe serait utilisée pour désérialiser l'interface de l'autre côté? Voir la première réponse – jwg

0

Vous avez inclus typeof (Liste < ...>), mais MyArray est de type IList < ...> ce qui n'est pas une structure de données apparente mais plutôt un espace réservé pour prendre une structure de données.

Modifiez le type de MyArray à un type spécifique (en tant que Liste, par exemple) et cela devrait fonctionner.

private List<Class2> myArray; 

    public List<Class2> MyArray 
    { 
     get { return myArray; } 
     set { myArray = value; } 
    } 
10

Voici un contournement ombragé non testé que je tendance à utiliser en principe:

private IList<Class2> myArray; 
[XmlIgnore] 
public IList<Class2> MyArray 
{ 
    get { return myArray; } 
    set { myArray = value; } 
} 

[XmlElement("MyArray")] 
public object MyArraySerializable 
{ 
    get { return MyArray; } 
    set { MyArray = value as IList<Class2>; } 
} 

Cela sérialisation quelle que soit la liste que vous pouvez utiliser comme objet générique avec un attribut de type qui dira désérialiseur le réel type de l'objet, donc quand cet objet est désérialisé, il doit à nouveau être converti en IList<Class2>. N'oubliez pas de fournir tous les types pouvant être pris en charge par l'interface.


Je ne vois pas pourquoi un sérialiseur devrait être incapable de sérialiser de telles propriétés. Ce n'est pas comme si vous essayiez réellement de sérialiser une interface, vous essayez de sérialiser un objet qui implémente une certaine interface (ce qui n'est pas très différent du sous-classement abstrait, certains langages de programmation fonctionnent même uniquement sur des interfaces).

Lorsque le sérialiseur doit sérialiser cet objet il sait que l'objet implémente cette interface, tout ce qu'elle a à faire est la sérialisation et attacher l'attribut type (comme il le fait si vous sérialiser classes abstraites ou juste super-classes en général).

Maintenant, le désérialiseur regarde le type et peut vérifier si cet objet implémente en fait l'interface requise et la désérialise ensuite à la propriété correspondante.

+0

Amen. Le sérialiseur est stupide quand il s'agit de ça! Merci pour le travail. Il est préférable d'utiliser les interfaces car l'héritage est limité à une classe de base. – toddmo

8

Ou utilisez le DataContractSerializer à la place.

+1

C'est en effet la bonne réponse. http://blogs.msdn.com/b/sowmy/archive/2008/10/04/serializing-internal-types-using-xmlserializer.aspx – l33t