我在序列化和反序列化具有 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));
}
}
}
这是输出:
<?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>
为什么是List<T>
XmlSerializer 的处理方式与数组不同,我可以做些什么来改变这种行为?
最佳答案
有趣;我过去从未注意到这一点,但它绝对是可重现的。由于 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;
}
}
关于c# - 具有默认值的 XmlSerializer 和 List<T>,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4217139/