2011-01-10 3 views
1

J'ai une liste d'objets qui implémentent une interface commune. Si je tente simplement sérialiser je reçois une belle exception qui me dit que le sérialiseur ne peut pas sérialiser interfaces:Erreur XmlSerializer Sérialisation des objets d'interface

private readonly ObservableCollection<ICanHasInterface> children = new ObservableCollection<ICanHasInterface>(); 
public ObservableCollection<ICanHasInterface> Children 
{ 
    get { return children; } 
} 

=> « Impossible de sérialiser membre ... de type ... parce qu'il est une interface »
Apparemment, demander au sérialiseur d'obtenir le type des objets et de marquer le XmlElement avec l'attribut xsi:type (ce qui est fait si un objet hérite d'une autre classe) est trop important.
parce que je ne veux pas mettre en œuvre IXmlSerializable, je pensais une solution qui semblait prometteuse au départ:

private readonly ObservableCollection<ICanHasInterface> children = new ObservableCollection<ICanHasInterface>(); 
[XmlIgnore()] 
public ObservableCollection<ICanHasInterface> Children 
{ 
    get { return children; } 
} 

[XmlElement("Child")] 
public List<object> ChildrenSerialized 
{ 
    get 
    { 
     return new List<object>(Children); 
    } 
    set 
    { 
     Children.Clear(); 
     foreach (var child in value) 
     { 
      if (child is ICanHasInterface) AddChild(child as ICanHasInterface); 
     } 
    } 
} 

Avec ce au moins la sérialisation fonctionne très bien (Remarque: Soit spécifier XmlInclude attributs pour les types qui peuvent être dans la liste d'origine ou remettre un tableau de types dans le constructeur du sérialiseur), cependant si l'objet est désérialisé, la collection Children finit vide parce que le bloc set n'est jamais atteint pendant la désérialisation, je ne sais vraiment pas pourquoi est; des idées?

Répondre

1

Lors de la désérialisation, le sérialiseur utilise votre propriété getter pour obtenir l'instance de collection, puis appelle Add() pour chaque élément. Il n'appelle pas votre régleur de propriété. Quelque chose comme ceci:

YourClass c = new YourClass(); 
c.ChildrenSerialized.Add(ReadValue()); 
... 

Afin de garder les collections synchronisés, vous aurez besoin de personnaliser le comportement Ajouter() de la collection que vous revenez du getter de la propriété.

Une meilleure option consiste à modifier la propriété ChildrenSerialized pour utiliser un objet []. Pour les tableaux, le sérialiseur lit la valeur dans un tableau, puis appelle votre setter de propriété avec la valeur.

+0

Merci beaucoup, fonctionne parfaitement avec un tableau! –

Questions connexes