views:

249

answers:

2

I have an array of elements that I need to serialize using XmlSerializer. The problem I'm having is I have 2 derived classes, and serializing them so they have an element name of the common base, doesn't seem to work.

So, this is how the XML should look:

<Root>
    <Base> foo </Base>
</Root>

Instead, I'm getting

<Root>
    <Derived1> foo </Derived1>
</Root>

The code for the array of elements I am serializing is

private object[] m_nodes;

[System.Xml.Serialization.XmlElementAttribute("Base", typeof(Derived1)]
[System.Xml.Serialization.XmlElementAttribute("Base", typeof(Derived2)]

public object[] Nodes
{
    get
    {
        return this.m_nodes;
    }
    set
    {
        this.m_nodes = value;
    }
}

With the above code, I get that there is a reflection error with Nodes. If I change "Base" in both XmlEelementAttributes to "Derived1" and Derived2", it works, but the element name is incorrect.

[System.Xml.Serialization.XmlInclude(typeof(Derived1))]
public abstract class Base
{
    public Base()
    {

    }
}



[System.SerializableAttribute()]
[System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true)]
public class Derived1: Base
{
    public Derived1()
    {

    }
}

Any help is greatly appreciated. Thanks so much.

+3  A: 

The XML Serialisation includes both serialising and deserialising routines. Therefore if you actually managed to do this then the serialiser would not be able to work out what type to use when deserialising the resulting XML structure. From my experience it is better to either use two different names or use a custom serialiser/deserialiser using the XmlWriter and XmlReader classes.

David McEwing
+1  A: 

David's answer is correct. This is not possible with bare XmlSerialization since it can't determine which of the derived classes should be instantiated when deserialising, from the content of the XML element.

If it's possible to use two different names it would work. They don't have to be the same name as the derived classes, you just need to give XmlSerialization a clue to determine which is which.

Custom serialization using XmlReader/Writer is always possible, but it is more time consuming than simple XmlSerialization (specially if you're not an experienced XML addict!)

What I do in such cases is to create a intermediate hierarchy of classes, and write simple conversions in code. So, the original objects are first converted into an intermediate structure which can be handled by the XmlSerialization.

For example, in your case, you can create a class analogous to Base (I call it BaseSerializable), and fill the data of Derived1 and Derived2 into that. The BaseSerializable can be handled by XmlSerialization. When deserializing you get a BaseSerializable from the XmlSerialization and then determine (using content of the fields/properties) which of the Derived1/Derived2 classes should be instantiated. So, in practice, you code a very small part of the serialization with your custom code and leave the rest to the XmlSerialization library.

Iravanchi
Thanks. Yours and David's answers make sense now that I look at it from the point of view of needing to deserialise as well. I think I had assumed there was some way of specifying that since some attribute="Derived1" in the XML, that I could manually tell it which object to create.
mattjf