2013-03-27 68 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将构建一个实例本身,反序列化它,并将其设置为其父项,就像任何其他非集合属性值一样。

相关问题