XmlSerializer和List <T>具有默认值

Mar*_*tin 12 .net c# xml generics xml-serialization

我在序列化时观察到一种奇怪的行为,而不是反序列化具有类型成员的类,该类List<T>在构造时填充了默认值.与基于数组的属性不同List<T>,XmlSerializer在反序列化时不会清空类型的属性.

这是我的代码:

public class Program
{
    public class Config
    {
        public Config()
        {
            Test1 = new List<string>()  {"A", "B"};
            Test2 = new String[] {"A", "B"};
        }
        public List<string> Test1 {get;set;}
        public string[] Test2 {get;set;}
    }

    public static void Main()
    {
        XmlSerializer xmlSerializer =
            new XmlSerializer(typeof(Config));
        using(Stream s = new MemoryStream())
        {
            xmlSerializer.Serialize(s, new Config());
            s.Position = 0;
            xmlSerializer.Serialize(Console.Out,
                xmlSerializer.Deserialize(s));
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

这是输出:

<?xml version="1.0" encoding="ibm850"?>
<Config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:xsd="http://www.w3.org/2001/XMLSchema">
  <Test1>
    <string>A</string>
    <string>B</string>
    <string>A</string>
    <string>B</string>
  </Test1>
  <Test2>
    <string>A</string>
    <string>B</string>
  </Test2>
</Config>
Run Code Online (Sandbox Code Playgroud)

为什么List<T>XmlSerializer处理的方式不同于数组,我该怎么做才能改变这种行为?

Mar*_*ell 5

有趣; 我以前从未注意到它,但它绝对可以重现.既然XmlSerializer不支持序列化回调(为了帮助你知道它正在运行序列化),这很难影响; 可以说最简单的答案是"不要将默认数据放入构造函数中的对象"(尽管可能提供了一种工厂方法).

可以尝试实现IXmlSerializable,但即使是一个简单的例子,这也很难做到.

不过,我已经检查过,并且DataContractSerializer 没有这样做 - 所以你可以切换到DataContractSerializer; 这是我的DCS测试代码:

DataContractSerializer ser =
    new DataContractSerializer(typeof(Config));
using (Stream s = new MemoryStream())
{
    ser.WriteObject(s, new Config());
    s.Position = 0;
    using(var writer = XmlWriter.Create(Console.Out)) {
        ser.WriteObject(writer, ser.ReadObject(s));
    }
}
Run Code Online (Sandbox Code Playgroud)

这就是我所说的工厂方法:

public class Config
{
    public Config()
    {
        Test1 = new List<string>();
        Test2 = nix;
    }
    public List<string> Test1 { get; set; }
    public string[] Test2 { get; set; }

    private static readonly string[] nix = new string[0];
    public static Config CreateDefault()
    {
        Config config = new Config();
        config.Test1.Add("A");
        config.Test1.Add("B");
        config.Test2 = new string[2] { "A", "B" };
        return config;
    }
}
Run Code Online (Sandbox Code Playgroud)