使用XML序列化时的循环引用?

尝试使用XMLSerialization序列化对象时,我收到以下exception。

A circular reference was detected while serializing an object of type MyObject}

我知道循环引用是因为childObject可以有childObjectparentObjectparentObjectparentObject ,但是如果可能的话我想保留该引用。 有没有办法让这个对象在XML序列化中序列化而不会在序列化过程中丢失任何数据? 我对序列化并不熟悉,所以我希望我能设置一些属性。

根据序列化器类型,有几个选项。

如果您可以使用DataContractSerializer或BinaryFormatter,那么您可以使用OnSerializedAttribute并将子对象的Parent属性设置为:

 [Serializable] public class Child { public string Foo { get; set; } public Parent Parent { get { return parent; } set { parent = value; } } // We don't want to serialize this property explicitly. // But we could set it during parent deserialization [NonSerialized] private Parent parent; } [Serializable] public class Parent { // BinaryFormatter or DataContractSerializer whould call this method // during deserialization [OnDeserialized()] internal void OnSerializedMethod(StreamingContext context) { // Setting this as parent property for Child object Child.Parent = this; } public string Boo { get; set; } public Child Child { get; set; } } class Program { static void Main(string[] args) { Child c = new Child { Foo = "Foo" }; Parent p = new Parent { Boo = "Boo", Child = c }; using (var stream1 = new MemoryStream()) { DataContractSerializer serializer = new DataContractSerializer(typeof (Parent)); serializer.WriteObject(stream1, p); stream1.Position = 0; var p2 = (Parent)serializer.ReadObject(stream1); Console.WriteLine(object.ReferenceEquals(p, p2)); //return false Console.WriteLine(p2.Boo); //Prints "Boo" //Prints: Is Parent not null: True Console.WriteLine("Is Parent not null: {0}", p2.Child.Parent != null); } } } 

如果要使用XmlSerializer ,则应实现IXmlSerializable ,使用XmlIgnoreAttribute并在ReadXml方法中实现或多或少相同的逻辑。 但在这种情况下,您还应手动实现所有Xml序列化逻辑:

 [Serializable] public class Child { public Child() { } public string Foo { get; set; } [XmlIgnore] public Parent Parent { get; set; } } [Serializable] public class Parent { public Parent() { } #region IXmlSerializable Members public System.Xml.Schema.XmlSchema GetSchema() { throw new NotImplementedException(); } public void ReadXml(System.Xml.XmlReader reader) { //Reading Parent content //Reading Child Child.Parent = this; } public void WriteXml(System.Xml.XmlWriter writer) { //Writing Parent and Child content } #endregion public string Boo { get; set; } public Child Child { get; set; } } 

如果可以使用DataContractSerializer而不是XMLSerializer,则可以在DataContract属性上使用IsReference属性。 启用此选项将保留引用,以便在反序列化时重新创建它们。

DataContractSerializer也序列化为XML,但您对输出的外观稍有不同,您可以使用较旧的XMLSerializer。 您可以在此处阅读有关序列化器的更多信息: http : //www.danrigsby.com/blog/index.php/2008/03/07/xmlserializer-vs-datacontractserializer-serialization-in-wcf/

将parentObject属性标记为[NonSerialized]。

http://blog.kowalczyk.info/article/Serialization-in-C.html