Circular Reference when using XML Serialization?

If you can use the DataContractSerializer instead of the XMLSerializer then you can use the IsReference property on the DataContract attribute. Enabling this will keep the references, so that they will be recreated upon deserialization.

The DataContractSerializer also serializes to XML, but you have somewhat less control over what the output looks like, that you do with the older XMLSerializer. You can read more about the serializers here: http://www.danrigsby.com/blog/index.php/2008/03/07/xmlserializer-vs-datacontractserializer-serialization-in-wcf/


Mark the parentObject property as [NonSerialized].

https://blog.kowalczyk.info/article/8n/serialization-in-c.html


There are several options depending on serializer type.

If you could use DataContractSerializer or BinaryFormatter then you may use OnSerializedAttribute and set Parent property for your child object to this:

[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);
        }
    }

}

If you want to use XmlSerializer you should implement IXmlSerializable, use XmlIgnoreAttribute and implemented more or less the same logic in ReadXml method. But in this case you should also implement all Xml serialization logic manually:

[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; }
}