2011-01-10 79 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