TOC
集合
using System; using System.Collections.Generic; using System.Xml.Serialization; using System.IO; namespace ConsoleApplication1 { class Program { static void Main(string[] args) { var f = new XmlSerializer(typeof(TestClass)); using (var sw = new StringWriter()) { f.Serialize(sw, new TestClass()); using (var sr = new StringReader(sw.ToString())) { var bt = (TestClass) f.Deserialize(sr); Console.WriteLine(bt.ListIdentical()); } } } } public class TestClass { private List<int> PrivateList; public List<int> MyList; public bool ListIdentical() { return PrivateList == MyList; } public TestClass() { PrivateList = new List<int>() { 123, 567 }; MyList = PrivateList; } } }
运行结果为 `True` 。实际上,如果把 `MyList` 换成只读属性,只要其值非 null / Nothing,则程序仍可以正常运行。
也就是说,反序列化过程复用了已有的集合实例。
发生变化的类
using System; using System.Xml.Serialization; using System.IO; namespace ConsoleApplication1 { class Program { static void Main(string[] args) { var f = new XmlSerializer(typeof(TestClass)); var f1 = new XmlSerializer(typeof(TestClass1)); using (var sw = new StringWriter()) { f.Serialize(sw, new TestClass()); using (var sr = new StringReader(sw.ToString())) { var tc1 = (TestClass1) f1.Deserialize(sr); Console.WriteLine("{0}, {1}", tc1.Value1, tc1.Value2); } } } } public class TestClass { public int Value1 = 10; } [XmlType("TestClass")] public class TestClass1 { public int Value1 = 20; public int Value2 = 30; } }
运行结果为
10, 30
说明反序列化过程中可以自动跳过缺失 XML 元素的属性/字段。
字典
XML 序列化不支持所有实现 IDictionary 接口的类。
可以替代的方法:自定义XML序列化Dictionary<int, string=””>
循环引用
using System; using System.Collections.Generic; using System.IO; using System.Xml.Serialization; namespace ConsoleApplication1 { class Program { private static void Main(string[] args) { var f = new XmlSerializer(typeof(TestClass)); using (var sw = new StringWriter()) { var tc = new TestClass(); tc.MyList = new List<MyClass>(){new MyClass(), new MyClass()}; tc.Ref = tc.MyList[0]; f.Serialize(sw, tc); Console.WriteLine(sw.ToString()); } } } public class TestClass { public List<MyClass> MyList; public MyClass Ref; } public class MyClass { public int Value; } }
运行结果如下
<?xml version="1.0" encoding="utf-16"?> <TestClass xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema"> <MyList> <MyClass> <Value>0</Value> </MyClass> <MyClass> <Value>0</Value> </MyClass> </MyList> <Ref> <Value>0</Value> </Ref> </TestClass>
`XmlSerializer`对循环引用处理的方法为按值展开。要解决这一问题,可以手动实现`IXmlSerializable`,或者使用`DataContractSerializer`。具体的处理方法可以参考:
WCF 第六章 序列化与编码 保留引用和循环引用。