Когда класс унаследован от List <>, XmlSerializer не сериализует другие атрибуты

У меня здесь ситуация, мне нужно, чтобы мой класс наследовался от List<ItemType>, но когда я это делаю, XmlSerializer не сериализует какое-либо свойство или поле, объявленные в моем классе, следующий пример демонстрирует:

public partial class Form1 : Form
{
    public Form1()
    {
        InitializeComponent();
        DoSerialize();
    }
    private void DoSerialize()
    {
        MyClass obj = new MyClass();
        obj.Add(1);
        obj.Add(2);
        obj.Add(3);
        XmlSerializer s = new XmlSerializer(typeof(MyClass));
        StringWriter sw = new StringWriter();
        s.Serialize(sw, obj);
    }
}
[Serializable]
[XmlRoot]
public class MyClass : List<int>
{
    public MyClass()
    {
    }
    int myAttribute = 2011;
    [XmlAttribute]
    public int MyAttribute
    {
        get
        {
            return myAttribute;
        }
        set
        {
            myAttribute = value;
        }
    }
}

полученный XML:

<?xml version="1.0" encoding="utf-16"?>
<ArrayOfInt xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
  <int>1</int>
  <int>2</int>
  <int>3</int>
</ArrayOfInt>

Ответ 1

Это по дизайну. Я не знаю, почему это решение было принято, но указано в документации:

  • Классы, реализующие ICollection или IEnumerable. Только коллекции сериализованные, а не публичные свойства.

(Смотрите раздел "Элементы, которые могут быть сериализованы" ). Кто-то подал на него ошибку, но он не будет изменен - здесь Microsoft также подтверждает, что не включая свойства для классов, реализующих ICollection, на самом деле поведение XmlSerializer.

Обходной путь был бы следующим:

  • Внедрите IXmlSerializable и выполните сериализацию самостоятельно.

или

  • Измените MyClass, чтобы он имел общедоступное свойство типа List (и не подклассифицировал его).

или

  • Используйте DataContractSerializer, который обрабатывает этот сценарий.

Ответ 2

Здесь вам нужно подумать.

У вас может быть класс, который является классом контейнера следующим образом:

class ContainerObject
{
     public int MyNewProperty { get; set; }

     [XmlElement("")]
     public List<int> MyList { get; set; }
}

Хитрость заключается в том, чтобы XmlElement name = "" над элементом List.

Когда это сериализуется в xml, вы будете иметь:

<ContainerObject>
   <MyNewProperty>...</MyNewProperty>

   <int>...</int>
   <int>...</int>

</ContainerObject>

Если вам нравится, вы также можете создать другой класс для элементов в списке

 class MyItem
 {
     public int MyProperty {get;set;} 

 } 

а затем вместо List of ints имеет список MyItems.

Это вы управляли именем XmlElement каждого элемента в списке.

Надеюсь, это было полезно.