C# Xml Serializer 将列表反序列化为 0 而不是 null [英] C# Xml Serializer deserializes list to count of 0 instead of null

查看:30
本文介绍了C# Xml Serializer 将列表反序列化为 0 而不是 null的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我对 XmlSerializer 在幕后工作.我有一个将 XML 反序列化为对象的类.我看到的是以下两个元素,它们不是被反序列化的 Xml 的一部分.

I am confused on how XmlSerializer works behind the scenes. I have a class that deserializes XML into an object. What I am seeing is for the following two elements that are NOT part of the Xml being deserialized.

[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; }
    }
}

我们以下面的 XML 为例:

Let's take the following XML as an example:

<MyClass>
  <SomeNode>value</SomeNode>
</MyClass>

您注意到测试和注释不是 XML 的一部分.

You notice that Tests and Comments are NOT part of the XML.

当这个 XML 被反序列化时,Comments 为空(这是预期的),而 Tests 是一个计数为 0 的空列表.

When this XML gets deserialized Comments is null(which is expected) and Tests is an empty list with a count of 0.

如果有人能向我解释这一点,我将不胜感激.我更喜欢的是,如果 XML 中缺少 <Tests> 那么列表应该保持为空,但是如果一个(可能是空的)节点 <Tests/> 存在,那么列表应该被分配.

If someone could explain this to me it would be much appreciated. What I would prefer is that if <Tests> is missing from the XML then the list should remain null, but if a (possibly empty) node <Tests /> is present then the list should get allocated.

推荐答案

您所观察到的是,引用诸如 List 之类的可修改集合的成员会被 自动预先分配XmlSerializer 开始反序列化.我不知道有任何地方记录了这种行为.它可能与此答案中描述的行为有关使用代码默认值对集合属性进行 XML 反序列化,这说明了这一点,因为 XmlSerializer 支持添加到只获取和预分配的集合,如果预分配的集合包含默认项,那么反序列化的项将被附加到它 - 可能会重复内容.Microsoft 可能只是选择在反序列化开始时预先分配所有可修改的集合,作为实现此目的的最简单方法.

What you are observing is that members referring to modifiable collections such as List<T> are automatically pre-allocated by XmlSerializer at the beginning of deserialization. I am not aware of any place where this behavior is documented. It may be related to the behavior described in this answer to XML Deserialization of collection property with code defaults, which explains that, since XmlSerializer supports adding to get-only and pre-allocated collections, if a pre-allocated collection contains default items then the deserialized items will be appended to it - possibly duplicating the contents. Microsoft may simply have chosen to pre-allocate all modifiable collections at the beginning of deserialization as the simplest way of implementing this.

该答案的解决方法,即使用代理数组属性,也适用于此处.由于无法追加数组,XmlSerializer 必须累积所有值并在反序列化完成后将它们设置回原处.但如果从未遇到相关标记,XmlSerializer 显然不会开始累积值,因此不会调用数组设置器.这似乎阻止了您不想要的集合的默认预分配:

The workaround from that answer, namely to use a surrogate array property, works here as well. Since an array cannot be appended to, XmlSerializer must accumulate all the values and set them back when deserialization is finished. But if the relevant tag is never encountered, XmlSerializer apparently does not begin accumulating values and so does not call the array setter. This seems to prevent the default pre-allocation of collections that you don't want:

[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);
        }
    }
}

示例 .Net fiddle 显示 Tests 仅在适当时分配.

Sample .Net fiddle showing that Tests is allocated only when appropriate.

这篇关于C# Xml Serializer 将列表反序列化为 0 而不是 null的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆