XmlSerializer无法处理循环引用因其设计不跟踪已序列化对象,导致重复序列化引发异常。可改用DataContractSerializer并启用PreserveObjectReferences,或重构模型、使用IXmlSerializable自定义逻辑。
XmlSerializer 在 C# 中不支持对象图中的循环引用。当两个对象相互引用(例如 A 引用 B,B 又引用 A),在序列化时会引发无限递归,最终导致 StackOverflowException 或抛出异常。
XmlSerializer 设计上是基于类型定义生成 XML 结构的,它不能跟踪已序列化的对象实例。因此,当遇到同一对象被多次引用或存在循环引用时,它无法识别“这已经是处理过的对象”,从而重复序列化,造成死循环或异常。
最直接的方式是换用支持循环引用的序列化器:
示例(DataContractSerializer):
[DataContract(IsReference = true)] public class Person { [DataMember] public string Name { get; set; }
[DataMember] public Person Spouse { get; set; }} // 序列化时启用 PreserveObjectReferences var serializer = new DataContractSerializer(typeof(Person), null, int.MaxValue, false, true, new XmlWriterSettings { Indent = true });
如果必须使用 XmlSerializer,需打破循环引用结构:
示例:
public class Parent
{
public string Name { get; set; }
public List Children { get; set; }
}
public class Child
{
public string Name { get; set; }
// 不保留 Parent 引用,或标记为 [XmlIgnore]
[XmlIgnore]
public Parent Parent { get; set; }
}
实现 IXmlSerializable 接口,手动控制序列化过程,跳过循环部分或记录已处理的对象。
这种方式复杂度高,适用于特殊场景,一般建议优先考虑前两种方案。
基本上就这些。XmlSerializer 本身不支持循环引用,推荐改用 DataContractSerializer 并开启 IsReference 支持,或调整数据结构避免循环。简单直接,避免踩坑。