Поведение по умолчанию для XMLSerializer входит в цикл, поскольку в качестве части попытки выяснить, как сериализовать BindingNode
, он затем пытается выяснить, как сериализовать IEnumerable<BindingNode>
, и для этого пытается вычислить как сериализовать BindingNode
.
Нельзя сказать, что вы не можете BindingNode
реализовать IEnumerable<BindingNode>
, просто поведение XMLSerializer по умолчанию не будет работать.
Если вы реализуете IXmlSerializable, вы сами контролируете сериализацию. Поскольку вы уже знаете структуру BindingNode, вам не нужно работать с ней во время выполнения! Если у вас есть гарантия ациклического графа (невозможно иметь BindingNode, который является его предком), то это тривиально:
public void WriteXml(XmlWriter writer)
{
writer.WriteStartElement("BindingNode");
//More stuff here.
foreach(BindingNode contained in this)
contained.WriteXml(writer);
writer.WriteEndElement();
}
Если график может быть циклическим, то это немного сложнее, так как вместо записи элемента со всеми включенными деталями вам нужно написать элемент, который ссылается на узел, уже сериализованный в поток, как в противном случае фактическая запись продолжается вечно, и если вам повезет, вы довольно скоро столкнетесь с другой причиной переполнения стека (если вам не повезло, программа весело сначала записывает концерты и файлы на диск, а затем нажимает на них).
public int SomeSortOfUniqueID
{
get
{
//guess what this property has to do!
}
}
public void WriteXml(XmlWriter writer)
{
WriteXml(writer, new HashSet<BindingNode>());
}
private void WriteXml(XmlWriter writer, HashSet<BindingNode> alreadyWritten)
{
if(alreadyWritten.Add(this))
{
writer.WriteStartElement("BindingNode");
writer.WriteAttributeString("uniqueID", SomeSortOfUniqueID.ToString());
//More stuff here.
foreach(BindingNode contained in this)
contained.WriteXml(writer, alreadyWritten);
writer.WriteEndElement();
}
else
{
//we need to reference a node already mentioned in the document.
writer.WriteStartElement("BindingNode");
writer.WriteAttributeString("refID", SomeSortOfUniqueID.ToString());
writer.WriteEndElement();
}
}
Конечно, вам также потребуется реализовать ReadXml () для повторного анализа XML.