1

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.

mfanto
  • 14,168
  • 6
  • 51
  • 61

3 Answers3

5

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
  • 3,320
  • 18
  • 16
1

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
  • 5,139
  • 9
  • 40
  • 56
  • 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. – mfanto Oct 13 '09 at 23:38
0

After a long search for alternatives, I found the following post here on Stack Overflow: How do I use an XmlSerializer to deserialize an object that might be of a base or derived class without knowing the type beforehand?

I tried it and it works, also for serialisation. So when serializing, it also gives you a nice output. For an array, you need to use the XmlArrayItem attribute.

Community
  • 1
  • 1