2011-01-10 98 views
1

我有一个实现通用接口的对象列表。如果我尝试简单的序列化它,我得到一个不错的异常告诉我,该串行不能序列接口:XmlSerializer错误序列化接口对象

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

=>“无法序列成员...类型的...因为它是一个接口”

显然要求序列化程序获取对象的类型并用属性xsi:type(如果对象从另一个类继承)标记XmlElement太多。
,因为我不想要实现IXmlSerializable,我想出了一个解决办法,其看起来最初有为:

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); 
     } 
    } 
} 

有了这个至少系列化工作得很好(注:请指定XmlInclude属性的类型,可以在原始列表中或在串行器的构造函数中交出类型数组),但是如果对象被反序列化,则Children集合会变空,因为set块在反序列化期间永远不会到达,所以我对于为什么会这样是;有任何想法吗?

回答

1

关于反序列化,序列化程序使用属性获取器获取集合实例,然后为每个项目调用Add()。它不会调用你的属性设置器。例如:

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

为了保持同步的集合,您需要自定义您从属性获取器返回的集合的Add()行为。

更好的选择是将ChildrenSerialized属性更改为使用对象[]。对于数组,序列化程序将该值读入数组,然后使用该值调用属性设置器。

+0

非常感谢,与阵列完美配合! – 2011-01-10 21:06:06