How to use XmlSerializer from inside ReadXml()

261 Views Asked by At

I'm trying to understand how to use XmlSerializer to deserialize <n> instances of a nested class from within the ReadXml() method of the outer class. What I'm running into is that the nested call to XmlSerializer.Deserialize() causes nodes to be skipped.

The XML document looks something like this:

<outerType>
    <innerType id="1">structure</innerType>
    <innerType id="2">structure</innerType>
    <otherElement />
</outerType>

The rules for deserializing outerType require implementing IXmlSerializable. But innerType can be deserialized by just using XmlSerializer.Deserialize(). The ReadXml() method for OuterType ends up looking something like this:

public void ReadXml(System.Xml.XmlReader reader)
{
    while (reader.Read())
    {
        if (reader.Name == "innerType")
        {
            XmlSerializer innerSer = new XmlSerializer(typeof(InnerType));
            InnerType obj = (InnerType)innerSer.Deserialize(reader);
        }
        else
            // Do some other logic
    }
}

On the first time through the loop, the type variable receives the structure contained in the <innerType id="1"/> element. But the loop never encounters the <innerType id="2"/> element.

After playing with this in the debugger, I believe what's happening is that before the call to innerSer.Deserialize(), reader is pointing to the opening tag for <innerType id="1"/>, and immediately afterward, it's pointing to the opening tag for <innerType id="2"/>. At the top of the loop, the call to XmlReader.Read() advances reader to the next element, and <innerType id="2"/> is never read.

Some solutions I've seen for deserializing a collection of objects suggest something along the lines of:

            XmlSerializer innerSer = new XmlSerializer(typeof(InnerType));
            InnerType obj1 = (InnerType)innerSer.Deserialize(reader);
            InnerType obj2 = (InnerType)innerSer.Deserialize(reader);

but in my particular case, I need to work with <n> instances of InnerType.

What I've found to work is to create a second XmlReader, containing a copy of the InnerType sub-tree, as in:

            XmlSerializer innerSer = new XmlSerializer(typeof(InnerType));
            XmlReader subTree = reader.ReadSubtree();
            InnerType obj = (InnerType)innerSer.Deserialize(subTree);

Is this the intended way to do this? Is there a better way to do this without creating an additional reader?

0

There are 0 best solutions below