Когда класс унаследован от 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 каждого элемента в списке.
Надеюсь, это было полезно.