К основному контенту

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>

Комментарии

Популярные сообщения из этого блога

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

Читать этот пост в Telegraph. Другие посты в канале в Telegram. Кто только не расписывал уже пошаговые инструкции по этой теме. Однако, время идёт, ПО меняется, инструкции нуждаются в обновлении, а люди в современной России всё больше нуждаются в применении VPN. Я собираюсь описать все шаги для создания бесплатного сервера на Amazon EC2 с операционной системой Linux и необходимые команды для настройки VPN сервера на нём. Чтобы не повторяться о деталях, которые были много раз описаны на русскоязычных и англоязычных ресурсах, по ходу статьи я просто приведу целую кипу ссылок, где можно почерпнуть необходимую информацию, а где информация устарела - опишу подробнее что нужно сдеать. В итоге, сервер будет доступен для вас из любой точки планеты, с любой операционной системы, и бесплатно (с определёнными ограничениями по трафику). Шаг первый - Регистрируемся на Amazon AWS Нужно зайти на сайт https://aws.amazon.com/ru и сразу перейти к Регистрации, нажав одноимённую кнопку. При р

В помощь программисту: инструкции по работе с Ubuntu сервером

Программистам чаще приходится писать код и заботиться о его чистоте, правильных абстракциях в коде, корректных зависимостях и прочих сложностях профессии. При этом, настройка и обслуживание серверов, хоть и связанная область - это отдельный навык, необходимый не каждому, и помнить о котором в деталях сложно. Поэтому, я делаю ряд микро-инструкций, которыми буду пользоваться и сам, когда необходимо. Это не статьи, а пошаговые помощники, которые я буду дополнять и наполнять по мере надобности. Делаем бесплатный VPN на Amazon EC2 Создание ключей SSH Подключение к серверу через SSH Передача файла с Linux сервера наWindows машину Делаем VPN сервер на Ubuntu 20.04 используя OpenVPN и EasyRSA  Отображение GUI с Linux сервера на Windows машине

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

Между парадигмами разработки с Entity Framework (Code First, Model First, Database First) я выбрал промежуточную, потому что ни одна меня не устраивала полностью. В Code First меня радуют чистые POCO классы, но не устраивает невозможность моделирования базы. В Database First и Model First мне не нравится генерация EDMX и другого всего лишнего. Таким образом, я нашел для себя такое решение: 1. Я моделирую схему в любой удобной программе (тут любая внешняя программа моделирования, генерирующая SQL Server-совместимые скрипты генерации базы) Рис. Смоделированная схема БД. 2. Создаю базу в SQL Management Studio 3. Делаю Reverse Engineering базы в POCO классы (как в Code First) с помощью плагина Entity Framework Power Tools Рис. Установленный плагин для Reverse Engineer. Рис. Вот так делается Reverse Engineer базы данных в POCO классы. Рис. Результат генерации POCO классов на основе базы данных: папочка Models с готовым контекстом, классами объектов и маппинг-классами.