Сериализация списков с унаследованными типами

#c# #serialization #inheritance

#c# #сериализация #наследование

Вопрос:

Прямо сейчас я работаю с сериализацией в C # и столкнулся с проблемой, на которую, похоже, не могу найти ответа. Итак, у меня есть сериализуемый класс со списком другого сериализуемого класса в качестве свойства. Мне нужно было, чтобы у одного из элементов в списке было отдельное свойство, поэтому я создал подкласс и добавил его в список, как и раньше. Именно тогда возникли проблемы с сериализацией, поэтому я могу только представить, что списки не могут быть сериализованы с унаследованными классами в них, но почему? И как бы была достигнута аналогичная цель? В любом случае, вот пример того, чего я пытаюсь достичь:

 [Serializable]
public class aList
{
    [XmlElement]public List<b> list = new List<b>();

    public aList()
    {
        list.Add(new b());
        list.Add(new b());
        list.Add(new c());
    }
}

[Serializable]
public class b
{
    [XmlElement]public int prop1;
    [XmlElement]public string prop2;

    public b()
    {
        prop1 = 0;
        prop2 = String.Empty;
    }
}

[Serializable]
public class c : b
{
    [XmlElement]public bool prop3;

    public c() : base()
    {
        prop3 = false;
    }
}
  

Комментарии:

1. Обратите внимание, что Serializable это не имеет ничего общего с сериализацией XML. Это только для двоичной сериализации.

Ответ №1:

XmlInclude атрибуты. Они какие-то … неуклюжие. По сути, вы присваиваете своим классам атрибуты, которые дают сериализатору подсказки о вашем наследовании.

В частности:

 [Serializable]
[XmlInclude(typeof(c))]
public class b
{
    [XmlElement]
    public int prop1;

    [XmlElement]
    public string prop2;

    public b()
    {
        prop1 = 0;
        prop2 = String.Empty;
    }
}
  

Комментарии:

1. Согласно документации, этот атрибут используется в связи с контрактами данных, которые здесь не используются. Правильно?

2. Отредактировал ваш ответ. KnownType предназначено для DataContractSerializer , а не для XmlSerializer . Используйте XmlInclude вместо этого.

3. О да, я так много работал с DataContracts, что забыл о других :). Спасибо за исправление!

4. Приятно! Атрибут XmlInclude был правильным решением. Исправлены все мои проблемы, за исключением того, что я забыл конструктор без параметров для последнего типа, ха-ха. Спасибо всем, кто внес свой вклад!

5. Большое спасибо за это решение… Я потратил бесчисленное количество часов, пытаясь переработать всю свою архитектуру, прежде чем увидел это.

Ответ №2:

Можно попробовать использовать массив вместо списка. Массив является сериализуемым, если содержащийся в нем элемент является сериализуемым.