Max*_*eue 5 c# xml serialization xmlserializer
我XmlSerializer对幕后工作方式感到困惑。我有一个将XML反序列化为对象的类。我看到的是以下两个元素,它们不是正在反序列化的Xml的一部分。
[XmlRootAttribute("MyClass", Namespace = "", IsNullable = false)]
public class MyClass
{
private string comments;
public string Comments
{
set { comments = value; }
get { return comments; }
}
private System.Collections.Generic.List<string> tests = null;
public System.Collections.Generic.List<string> Tests
{
get { return tests; }
set { tests = value; }
}
}
Run Code Online (Sandbox Code Playgroud)
让我们以以下XML为例:
<MyClass>
<SomeNode>value</SomeNode>
</MyClass>
Run Code Online (Sandbox Code Playgroud)
您会注意到测试和注释不是XML的一部分。
对该XML进行反序列化时,Comment为null(这是预期的),而Tests是一个空列表,计数为0。
如果有人可以向我解释这一点,将不胜感激。我更希望的是,如果<Tests>XML中缺少该列表,则该列表应保持为空,但是如果存在(可能为空)节点<Tests />,则应分配该列表。
您观察到的是,引用可修改集合的成员,例如在反序列化开始时List<T>自动预先分配的成员。XmlSerializer我不知道有任何地方记录了这种行为。它可能与此答案中描述的行为有关XML Deserialization of collection property with code defaults,这解释了,由于XmlSerializer 支持添加到仅获取和预分配的集合,如果预分配的集合包含默认项目,则反序列化的集合项目将被附加到它 - 可能会重复内容。Microsoft 可能只是选择在反序列化开始时预先分配所有可修改的集合,作为实现此目的的最简单方法。
该答案的解决方法,即使用代理数组属性,在这里也适用。由于无法追加数组,因此XmlSerializer必须累积所有值并在反序列化完成时将它们设置回原位。但是,如果从未遇到相关标签,则XmlSerializer显然不会开始累积值,因此不会调用数组设置器。这似乎可以防止默认预分配您不想要的集合:
[XmlRootAttribute("MyClass", Namespace = "", IsNullable = false)]
public class MyClass
{
private string comments;
public string Comments
{
set { comments = value; }
get { return comments; }
}
private System.Collections.Generic.List<string> tests = null;
[XmlIgnore]
public System.Collections.Generic.List<string> Tests
{
get { return tests; }
set { tests = value; }
}
[XmlArray("Tests")]
public string[] TestsArray
{
get
{
return (Tests == null ? null : Tests.ToArray());
}
set
{
if (value == null)
return;
(Tests = Tests ?? new List<string>(value.Length)).AddRange(value);
}
}
}
Run Code Online (Sandbox Code Playgroud)
示例.Net fiddle显示Tests仅在适当时分配。