I’m trying to serialize the following class:
[Serializable()]
public class BindingNode : IEnumerable<BindingNode>
{
public BindingNode()
{
}
IEnumerator IEnumerable.GetEnumerator()
{
throw new NotImplementedException();
}
public IEnumerator<BindingNode> GetEnumerator()
{
throw new NotImplementedException();
}
public void Add(BindingNode item)
{
throw new NotImplementedException();
}
}
This was originally an ICollection instead of an IEnumerable, but I removed as much as I could of my code to keep only what caused the error. Here’s the code where the exception occurs:
private void button1_Click(object sender, EventArgs e)
{
BindingNode node = new BindingNode();
if (saveFileDialog1.ShowDialog() == DialogResult.OK)
{
Stream stream = File.Open(saveFileDialog1.FileName, FileMode.Create);
XmlSerializer xmlFormatter = new XmlSerializer(node.GetType());
xmlFormatter.Serialize(stream, node);
stream.Close();
}
}
The default behaviour for XMLSerializer is hitting a loop because as part of trying to work out how to serialse a
BindingNode, it then tries to figure out how to serialise anIEnumerable<BindingNode>, and to do that it tries to figure out how to serialise aBindingNode.There’s nothing to say that you can’t have
BindingNodeimplementIEnumerable<BindingNode>, just that the default XMLSerializer behaviour isn’t going to work.If you implement IXmlSerializable, then you control the serialisation yourself. Since you already know the structure of a BindingNode, you don’t have to work that out at runtime! If you’ve a guarantee of an acyclic graph (it’s impossible to have a BindingNode that is an ancestor of itself), then this is trivial:
If the graph can by cyclic, it’s just slightly more complicated in that you need to be able to instead of writing an element with all the details included, that you write an element that references a node already serialised to the stream, as otherwise the actual writing goes on forever and if you’re lucky you hit a different cause of a stack overflow pretty soon (if you’re unlucky the program merrily writes gigs and gigs of a file to disk first, and then hits it).
Of course, you’ll also have to implement ReadXml() to parse the XML back again.