2013-03-27 61 views
2

我有一個集合屬性是從BindingList繼承的自定義類型。目前,該屬性通過XmlSerializer被序列化,即使它沒有Setter。我現在試圖在這個自定義集合類上實現IXmlSerializable,並且如果我的集合屬性有一個Setter,那麼只會調用WriteXml()和ReadXml()接口方法。爲什麼序列化現在忽略此屬性,除非在沒有Setter的情況下沒有Setter之前就有Setter。實現IXmlSerializable需要集合屬性有安裝程序

重現:

首先,有人稱一類「項目​​」:

public class Item 
{ 
    public Item() {} 

    // Generates some random data for the collection 
    private MyCollectionType GenerateContent() 
    { 
     Random ranGen = new Random(); 
     MyCollectionType collection = new MyCollectionType(); 

     for (int i = 0; i < 5; i ++) 
     { 
      collection.Add("Item" + ranGen.Next(0,101)); 
     } 

     return collection; 
    } 

    public MyCollectionType Items 
    { 
     get 
     { 
      if (m_Items == null) 
      { 
       m_Items = GenerateContent(); 
      } 
      return m_Items; 
     } 
    } 
    private MyCollectionType m_Items = null; 
} 

接下來有創建集合類「MyCollectionType」(需要注意的是IXmlSerializable的是故意的片斷,開始失蹤用):

public class MyCollectionType : BindingList<string> 
{ 
    public MyCollectionType() 
    { 
     this.ListChanged += MyCollectionType_ListChanged; 
    } 

    void MyCollectionType_ListChanged(object sender, ListChangedEventArgs e){ } 

    public MyCollectionType(ICollection<string> p) 
    { 
     this.ListChanged += MyCollectionType_ListChanged; 
    } 

    #region Implementation of IXmlSerializable 

    public void WriteXml(XmlWriter writer) 
    { 
     throw new NotImplementedException(); 
    } 

    public void ReadXml(XmlReader reader) 
    { 
     throw new NotImplementedException(); 
    } 

    public XmlSchema GetSchema() { return null; } 

    #endregion 
} 

最後,加在main()一些代碼序列化和反序列化 「項目」:

 Item myItem = new Item(); 
     Item newItem = null; 

     // Define an XmlSerializer 
     XmlSerializer ser = new XmlSerializer(typeof(Item)); 

     // Serialize the Object 
     using (TextWriter writer = File.CreateText(@"c:\temporary\exportedfromtest.xml")) 
     { 
      ser.Serialize(writer,myItem); 
     } 

     // Deserialize it 
     using (Stream reader = new FileStream(@"c:\temporary\exportedfromtest.xml", FileMode.Open, FileAccess.Read, FileShare.Read)) 
     { 
      using (XmlDictionaryReader xmlDictionaryReader = XmlDictionaryReader.CreateTextReader(reader, XmlDictionaryReaderQuotas.Max)) 
      { 
       newItem = (Item)ser.Deserialize(xmlDictionaryReader); 
      } 
     } 

所以,如果你按原樣運行,你應該看到它在沒有Setter的情況下序列化和反序列化。目前,集合並沒有在上面的代碼片段中列出「IXmlSerializable」,但方法在那裏。所以,如果你現在回去向MyCollectionType類中添加「IXmlSerializable」並再次運行,你會注意到collection屬性沒有被序列化,WriteXml()和ReadXml()方法不會被調用。還要注意,如果你添加一個空Setter,這些方法會突然被調用。

+0

而這與WCF如何?請標記負責任:) – Tim 2013-03-27 15:30:07

+0

請張貼代碼。 – Romoku 2013-03-27 15:34:44

回答

2

這是記錄的行爲。據介紹,雖然不清,在Introducing XML Serialization

XML序列化不會轉換方法,索引器,私有字段或只讀屬性(除只讀的集合)。要序列化公共和私有對象的所有字段和屬性,請使用DataContractSerializer而不是XML序列化。

正如你所看到的,得到-屬性只有在一般不會被序列化 - 除只讀集合。但是微軟對此意味着什麼?畢竟集合並非財產。

他們的意思如下:

XML序列化不會轉換得到,只有屬性或只讀域(除了預加載集合得到只集合值屬性)

(順便說一句,這意味着,如果你在包含類型的構造函數將項目添加到您的收藏,然後進行序列化和反序列化,默認的項目將獲得複製。對於爲什麼,看到XML Deserialization of collection property with code defaults的解釋。如果我反序列化你的Item類,我看到這種行爲。)

這是如何適用於你的情況?那麼,當你使你的集合實現IXmlSerializable時,序列化器不再把它解釋爲一個集合;它將其解釋爲黑匣子。因此,它對收藏品的特殊規定不再適用。引用您的收藏集的屬性現在必須是可讀/寫的; XmlSerializer將構建一個實例本身,反序列化它,並將其設置爲其父項,就像任何其他非集合屬性值一樣。

相關問題