XmlSerializer序列化List需T为public类、含无参构造函数及public读写属性;须传typeof(List),支持Xml特性定制根名与命名空间,不支持私有字段、只读属性、Dictionary等。

用 XmlSerializer 序列化 List 是最直接的方式
只要类型 T 是公共类、有无参构造函数、所有要序列化的字段/属性是公共的,XmlSerializer 就能正常工作。它不支持私有字段、只读属性(除非有 public setter)、Dictionary 或匿名类型。
常见错误现象:InvalidOperationException 提示“无法序列化类型 System.Collections.Generic.List`1”,通常是因为没传入泛型类型的具体类型信息,或目标类里有不可序列化的成员。
- 必须显式传入
typeof(List构造) XmlSerializer,不能只传typeof(T) - 如果
T有自定义属性(如[XmlIgnore]、[XmlElement("Name")]),它们会生效 - 序列化结果中默认根元素名是
ArrayOfType,可通过包装类或XmlRoot特性控制
var list = new List{ new Person { Name = "Alice", Age = 30 }, new Person { Name = "Bob", Age = 25 } }; var serializer = new XmlSerializer(typeof(List )); using (var writer = new StringWriter()) { serializer.Serialize(writer, list); Console.WriteLine(writer.ToString()); }
Person 类必须满足基本可序列化要求
XmlSerializer 不会报错但静默跳过不可序列化成员,比如没有 getter/setter 的属性、internal 或 private 字段、static 成员。务必检查生成的 XML 是否包含预期字段。
容易踩的坑:忘记加无参构造函数,或把属性写成 public string Name { get; }(只读)——这会导致该字段不出现在 XML 中。
- 类必须是
public - 每个要序列化的属性必须有
publicgetter 和 setter - 必须有
public无参构造函数(编译器自动生成的也行) - 避免在属性 getter 中抛异常或访问外部资源
public class Person
{
public Person() { } // 必须存在
public string Name { get; set; } // ✅ 可序列化
public int Age { get; set; } // ✅ 可序列化
public string InternalId { get; private set; } // ❌ 不会出现在 XML 中
}
想自定义根节点名或去掉默认命名空间?用 XmlRoot 和 XmlSerializerNamespaces
默认输出带 xmlns:xsi 和 xmlns:xsd,多数场景不需要。根元素叫 ArrayOfPerson 也不够直观。这两个问题可以一起解决。
注意:XmlRoot 特性只能加在类上,对 List 本身无效;所以更稳妥的做法是封装一层容器类,或者用 XmlSerializer 构造时传入 XmlRootAttribute 实例。
- 传入
new XmlRootAttribute("People")可改根名 - 用
XmlSerializerNamespaces添加空前缀可移除默认命名空间 - 若用容器类(如
PeopleCollection),直接在类上加[XmlRoot("People")]更清晰
var serializer = new XmlSerializer(
typeof(List),
new XmlRootAttribute("People"));
var ns = new XmlSerializerNamespaces();
ns.Add("", ""); // 移除默认命名空间
using (var writer = new StringWriter())
{
serializer.Serialize(writer, list, ns);
Console.WriteLine(writer.ToString());
}
别用 DataContractSerializer 替代,除非你已绑定 WCF 场景
DataContractSerializer 默认不支持 List 直接序列化,且需要显式标记 [DataContract] 和 [DataMember],XML 格式也不同(带 xmlns:i 等)。它更适合服务间契约明确的场景,不是通用 XML 生成方案。
如果你只是导出配置、日志或简单数据交换,坚持用 XmlSerializer。混用两种序列化器容易导致反序列化失败或字段丢失。
-
XmlSerializer基于公有成员,约定优先,适合人读 XML -
DataContractSerializer基于显式契约,适合跨平台服务通信 - 二者生成的 XML 结构、命名空间、空值处理逻辑都不同,不能互换
T 类型嵌套了其他泛型集合、接口类型或含循环引用,XmlSerializer 会直接失败,而且错误信息非常模糊。这种时候要么重构模型,要么换 JSON。










