【问题标题】:XmlSerializer and List<T> with default valuesXmlSerializer 和 List<T> 具有默认值
【发布时间】:2011-05-12 03:43:37
【问题描述】:

我在序列化和反序列化具有List&lt;T&gt; 类型成员的类时观察到一种奇怪的行为,该成员在构造时填充了默认值。与基于数组的属性不同,List&lt;T&gt; 类型的属性在 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));
        }
    }
}

这是输出:

<?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>

为什么 XmlSerializer 对 List&lt;T&gt; 的处理方式与数组不同,我可以做些什么来改变这种行为?

【问题讨论】:

标签: c# .net xml generics xml-serialization


【解决方案1】:

有趣;我过去从未注意到这一点,但它绝对是可重现的。由于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));
    }
}

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

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

【讨论】:

    【解决方案2】:

    当列表包含一组在构造函数中创建的默认条目时,这确实是 XML 反序列化的令人沮丧的行为。

    我的解决方法是在 List 上设置 XMLIgnoreAttribute 并包含对象类型数组的公共成员,其中 set/get 处理来自数组的列表的填充。

    以下内容允许在构造函数中创建默认值,但会阻止 XML 序列化程序将条目添加到默认列表中。 (除了错误/空验证)。

    public class Config
    {
        public Config()
        {
            Test1 = new List<string>() { "A", "B" }; 
            Test2 = new String[] { "A", "B" };
    
        }
    
        [XmlIgnore]
        public List<string> Test1 { get; set; }
        public string[] Test2 { get; set; }
    
        // This member is only to be used during XML serialization
        public string[] Test1_Array 
        { 
            get
            {
                return Test1.ToArray();
            }
            set 
            {
                Test1 = value.ToList();
            }
        }        
    
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2010-12-12
      • 1970-01-01
      • 1970-01-01
      • 2017-12-16
      • 2023-03-30
      • 1970-01-01
      • 1970-01-01
      • 2018-12-22
      相关资源
      最近更新 更多