XML serialization of derived classes

Sometimes you need to serialize objects of derived classes in the XML. You may find a lot of blogs about how to do this on C#. But the most of them will give a simple answer to add an XmlInclude attribute on base class. In some cases this is not enough because of tricky logic inside of standard XML Serializer. Some people solved this problem by overriding the XML Serializer with more tricky one. This article will give an answer to solve one particle task about the serialization of derived classes, but probably this may help to find out ways to do this with less pain.

I had to create an XML file which presents the full structure of maps database entities (i.e. with indeces, parents and childs ids, etc.). I've got specifications from the client describing how the XML file should look like. Every tag in the XML should present the real entity in their database. But the main problem is that our database looks differently from the their ones. So I had to create a lot of wrappers staff to do this.

In one place I had to do the interesting mapping:

- At one side I have two different entity classes (let's suppose BlackKitten and WhiteKitten) which describes probably some close or related information, but these classes are not the members of inheritance. (Why? They are different tables...and this is the topic for another article about the bad designs in programming =) )

- On the other side I need to create such XML tags:


<Kittens>
    <Kitten /> <-- Here is info about Black Kitten -->
    <Kitten /> <-- Here is info about the White one -->
</Kittens>

So, to serialize this information you have to create the base Kitten class and inherit BlackKitten and WhiteKitten from it. I've created similar wrappers to get this done, but I've found another "showstopper" problem. XML Serializer threw exception when tried to work with it:

 

This happens because the Serializer doesn't know the types and we have to notice the types by setting XmlInclude attribute on base Kitten class. And...after doing this you will get the same exception again =). Many advices are stopped on this step and that is why I decided to write this article.

The next problem is how to map derived classes to the tags in the XML, if you need to present any derived XXXXXKitten class with the base Kitten tag name. The obvious way to give and element name or type name of course not work.

So, there is piece of code how to do this:


// Base Kitten class
[XmlInclude(typeof(BlackKitten))]
[XmlInclude(typeof(WhiteKitten))]
public abstract class Kitten
{
...
}
 
public class BlackKitten: Kitten
{
...
}
 
public class WhiteKitten: Kitten
{
...
}
 
// Container which keeps the different Kittens as one...
public class XMLContainer
{
    [XmlElement(ElementName = "Kitten",
     &nbsp                 Namespace = "BlackKitty",
     &nbsp                 Type = typeof(BlackKitten)),
    XmlElement(ElementName = "Kitten",
     &nbsp                 Namespace = "WhiteKitty",
     &nbsp                 Type = typeof(WhiteKitten))]
    public Kitten Kitten { get; set; }
}

And here we are!


<Kittens>
    <Kitten xmlns="MyNamespace.BlackKitty" />
    <Kitten xmlns="MyNamespace.WhiteKitty" />
</Kittens>

Комментарии

Популярные

Кастомизируем ASP.NET Identity 2.0

Делаем себе бесплатный VPN на Amazon EC2

Выбираем все плюсы из трех парадигм Entity Framework