XmlSerializer错误序列化接口对象

时间:2011-01-10 19:36:56

标签: c# interface xml-serialization

我有一个实现公共接口的对象列表。如果我尝试简单地序列化它,我得到一个很好的异常,告诉我序列化程序不能序列化接口:

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

=&GT; “无法序列化类型的成员......因为它是一个界面”

显然要求序列化程序获取对象的类型并使用属性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 个答案:

答案 0 :(得分:1)

在反序列化时,序列化程序使用属性getter获取集合实例,然后为每个项调用Add()。它不会调用您的属性设置器。像这样:

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

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

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