基本用法
C#中要将一个对象序列化到XML,或从XML反序列化需要用到 XmlSerializer 类。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57
| using System; using System.Collections.Generic; using System.IO; using System.Windows.Forms; using System.Xml.Serialization;
namespace WindowsFormsApp1 { public enum MyEnum { Enum1, Enum2 }
public class Cat { public int Color; }
public class Student { private int _val1; public int Val2; public MyEnum MyEnum; public int Val3 { get; } = 0; public int Val4 { get; set; } = 0; public int? Val5 = null;
public Cat MyCat = new(); public List<int> Arr1; public static int StaticVal; }
public partial class Form1 : Form { public Form1() { InitializeComponent(); }
private void button1_Click(object sender, EventArgs e) { var obj = new Student() { Arr1 = new List<int> { 10, 20 } };
var serializer = new XmlSerializer(obj.GetType()); using var fs = new FileStream("obj.xml", FileMode.Create); serializer.Serialize(fs, obj); } } }
|
输出XML内容
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| <?xml version="1.0"?> <Student xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema"> <Val2>0</Val2> <MyEnum>Enum1</MyEnum> <Val5 xsi:nil="true" /> <MyCat> <Color>0</Color> </MyCat> <Arr1> <int>10</int> <int>20</int> </Arr1> <Val4>0</Val4> </Student>
|
可见类成员并没有完全被序列化,因为 XmlSerializer 默认不会序列化以下几种数据:
- 静态成员,因为静态成员属于类而不是实例。
- 只读成员,因为只读成员在反序列化时不能被初始化。
- 私有成员,因为私有成员不能从外部访问,因此无法序列化和反序列化。
必须有默认构造函数
当类没有提供无参数构造函数时,构造 XmlSerializer 时就会抛出InvalidOperationException
异常
1
| Student 无法序列化,因为它没有无参数的构造函数。
|
实现 IXmlSerializable 接口
在某些情况下,XmlSerializer类的默认行为可能无法满足需求,这时就需要实现 IXmlSerializable 接口来控制序列化和反序列化过程
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34
| public class Student: IXmlSerializable { private int _val1; public int Val2; public MyEnum MyEnum; public int Val3 { get; } = 0; public int Val4 { get; set; } = 0; public int ? Val5 = null; public Cat MyCat = new(); public List < int > Arr1; public static int StaticVal; public XmlSchema GetSchema() { return null; } public void ReadXml(XmlReader reader) { Val2 = reader.ReadElementContentAsInt(); } public void WriteXml(XmlWriter writer) { writer.WriteValue(Val2); } }
|
输出XML内容
1 2
| <?xml version="1.0"?> <Student>0</Student>
|
一些需要实现IXmlSerializable接口的情况:
- 控制值的输出格式。
- 需要序列化私有成员时。
- 当需要在序列化过程中执行一些自定义的操作时,例如在序列化之前或之后执行某些操作,或者在序列化期间处理异常时。
注解
使用注解(Attribute)来为XML序列化和反序列化提供更多的控制和灵活性。
XmlRoot
XmlRoot 用于指定XML文档根元素名称和命名空间的注解。它可以应用于类或结构体,并且可以在序列化和反序列化过程中提供更多的控制和灵活性。
1 2 3 4 5 6
| [XmlRoot("Person", Namespace = "http://example.com")] public class Person { public string Name { get; set; } public int Age { get; set; } }
|
输出XML内容
1 2 3 4
| <Person xmlns="http://example.com"> <Name>Alice</Name> <Age>30</Age> </Person>
|
XmlElement
XmlElement 用于将类的属性或字段序列化为XML元素的注解。它可以应用于公共字段或属性,并且可以指定XML元素的名称和命名空间。
1 2 3 4 5 6 7 8
| public class Person { [XmlElement("FullName")] public string Name { get; set; } [XmlElement("Years")] public int Age { get; set; } }
|
输出内容
1 2 3 4
| <?xml version="1.0"?> <Person xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema"> <Years>0</Years> </Person>
|
在这个例子中,XmlElement 注解指定了节点元素的名称。更多用法参考 XmlElement
XmlAttribute
XmlAttribute 是用于将类的属性或字段序列化为XML属性的注解。它可以应用于公共字段或属性,并且可以指定XML属性的名称和命名空间。
1 2 3 4 5 6 7
| public class Person { public string Name { get; set; } [XmlAttribute("Years")] public int Age { get; set; } }
|
输出内容
1 2 3
| <Person Years="30"> <Name>Alice</Name> </Person>
|
在这个例子中,注解将Age属性序列化为XML属性,属性名为”Years”。更多用法参考 XmlAttributes
XmlArray
XmlArray 用于将数组或集合属性序列化为XML数组的注解。它可以应用于公共字段或属性,并且可以指定XML数组的名称、元素名称和命名空间。
1 2 3 4 5 6 7 8
| public class Person { public string Name { get; set; } [XmlArray("Interests")] [XmlArrayItem("Interest")] public string[] Interests { get; set; } }
|
在这个例子中,注解指定了生成的XML数组的名称为”Interests”。同时,XmlArrayItem注解指定了生成的XML数组元素的名称为”Interest”。
1 2 3 4 5 6 7 8
| <Person> <Name>Alice</Name> <Interests> <Interest>Reading</Interest> <Interest>Traveling</Interest> <Interest>Hiking</Interest> </Interests> </Person>
|
XmlIgnore
XmlIgnore 用于公共字段或属性,并用于指示XmlSerializer忽略该字段或属性的序列化。
1 2 3 4 5 6 7
| public class Person { public string Name { get; set; } [XmlIgnore] public int Age { get; set; } }
|
其他注解
还有一些其他不常用的注解参考官方手册 用来控制 XML 序列化的属性
相关阅读
如何:序列化对象
XML 序列化注意事项