Question

I am trying to serialize a tree structures using the objects provided below. I need to have the list of children serialized with the object, but I can live without the parent (since I can just fix that on de-serialization).

The problem I am having is that regardless if I have [XmlIgnore] or not, I still get this error.

A circular reference was detected while serializing an object of type 'DataEntry'

If I change the 'getter/setter' for the 'Parent' property to do nothing, it all work.

[XmlIgnore]
        public DataEntry Parent 
        {
            get { return null; }
            set {} 
        }

But I need this Parent reference to be available at a later stage.

public class DataEntry
    {
        [XmlIgnore]
        public DataEntry Parent { get; set; }

        public List<DataEntry> Children { get; set; }

        private List<String> mValues = new List<String>();
        public List<String> Values
        {
            get
            {
                return mValues;
            }
            set
            {
                mValues = value;
            }
        }

        private String mName = String.Empty;
        public String Name
        {
            get { return mName; }
            set
            {
                mName = value;
            }
        }

        /// <summary>
        /// Data entry
        /// </summary>
        /// <param name="partent">parent node - if root node give no parent</param>
        /// <param name="name">Name of property</param>
        /// <param name="values">Values for this property</param>
        public DataEntry(DataEntry partent, String name, List<String> values)
        {
            Children = new List<DataEntry>(); 
            Parent = partent;
            mValues = values;
            mName = name;
        }

        /// <summary>
        /// Add a child to this node
        /// </summary>
        /// <param name="child"></param>
        public void AddChild(DataEntry child)
        {
            Children.Add(child);
        }
    }

Any help would be much appreciated.

Was it helpful?

Solution

XML has a tree structure (nested tags). Your objects are connected as a graph (that is, with cycles).

You'll have to visit the graph, find the cycles and open them up by clipping the references. Once you obtain the spanning tree of the graph, you can serialize that.

But the clipped references will be lost. So you will want to store the clipped references to, besides the spanning tree.

Upon deserialization you'll want to deserialize the spanning tree and then the additional references that were clipped. So you'll rebuilt those references by re-establishing them between the objects.

If you can, try to avoid cycles in your graph by reducing it to the spanning tree already in there definition. This way you'll not have to do all that work just to serialize it.

On the other hand, removing those references may impact on the rest of the application, so you may not want to do that.

On another note: a well designed database has a normal form (often the third but there are others, too). Those concepts are pretty much related to one another.

This is a rough pseudo-C# guide:

xml = serialize(root)
{
    1. set all parents to null
    2. XML serialize
    3. rebuilt all parents <-- reuse rebuiltParents()
}

root = deserialize(xml)
{
    1. XML deserialize
    2. rebuilt all parents <-- reuse rebuiltParents()
}
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top