gpt4 book ai didi

c# - 实现 IXmlSerializable 需要集合属性具有 Setter

转载 作者:行者123 更新时间:2023-11-30 16:18:57 25 4
gpt4 key购买 nike

我有一个自定义类型的集合属性,它继承自 BindingList。目前,此属性通过 XmlSerializer 进行序列化,即使它没有 Setter。我现在正尝试在此自定义集合类上实现 IXmlSerializable,并发现只有在我的集合属性具有 Setter 时才会调用 WriteXml() 和 ReadXml() 接口(interface)方法。为什么序列化现在忽略此属性,除非在没有 Setter 的情况下正确序列化之前存在 Setter。

重现:

首先,有一个名为“Item”的类:

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”:

        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”,但方法在那里。因此,如果您现在返回并将“IXmlSerializable”添加到 MyCollectionType 类并再次运行,您会注意到集合属性未序列化,并且未调用 WriteXml() 和 ReadXml() 方法。另请注意,如果您添加一个空的 Setter,这些方法将突然被调用。

最佳答案

这是记录在案的行为。在 Introducing XML Serialization 中对此进行了解释,尽管不清楚。 :

XML serialization does not convert methods, indexers, private fields, or read-only properties (except read-only collections). To serialize all an object's fields and properties, both public and private, use the DataContractSerializer instead of XML serialization.

如您所见,只读属性通常不会序列化——只读集合除外。但微软的意思是什么?集合毕竟不是属性(property)。

他们的意思如下:

XML 序列化不转换只读属性或只读字段(具有预初始化集合的只读集合值属性除外)

(顺便说一句,这意味着,如果您在包含类型的构造函数中将项目添加到您的集合,然后对其进行序列化和反序列化,则默认项目将复制。有关原因的解释,请参见XML Deserialization of collection property with code defaults。如果我反序列化您的 Item 类,我会看到这种行为。)

这如何适用于您的情况?好吧,当您使集合实现 IXmlSerializable 时,序列化程序不再将其解释为集合;它将它解释为一个黑盒子。因此,它的特殊收藏规则不再适用。引用您的集合的属性现在必须是可读/可写的; XmlSerializer 将自己构造一个实例,对其进行反序列化,并将其设置到其父级中,就像任何其他非集合属性值一样。

关于c# - 实现 IXmlSerializable 需要集合属性具有 Setter,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15662277/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com