Есть такой класс:
public class ChapterCollection : ObservableCollection
При его сериализации в XML свойство IsSelectedAll не сериализуется. Только коллекция объектов ChapterVM
Как сериализовать свойство?
Сериализация происходит так:
public static void SerializeToXml(string path, object saveObject)
{
var formatter = new XmlSerializer(saveObject.GetType());
using (FileStream fs = new FileStream(path, FileMode.Create))
{
formatter.Serialize(fs, saveObject);
}
}
Ответ
Наиболее простым решением является отказ от наследования в пользу композиции. Действительно, логично предположить что ChapterCollection не просто "является" коллекцией ChapterVM, а содержит в себе коллекцию ChapterVM и также некоторые другие свойства, как признак выделенности элементов коллекции и т.п.
Зы. Недаром умные книги по проектированию пишут
Предпочитайте композицию наследованию
Если всё же вы намерены оставить наследование, для переопределения действий сериализатора необходимо реализовать интерфейс IXmlSerializable. Сделать это можно примерно так:
public class ChapterCollection : ObservableCollection
public XmlSchema GetSchema() => null;
public void ReadXml(XmlReader reader)
{
reader.ReadStartElement();
// Читаем из потока дополнительные свойства вручную
IsSelectedAll = reader.ReadElementContentAsBoolean(nameof(IsSelectedAll), "");
// Читаем элементы коллекции
XmlSerializer ser = new XmlSerializer(typeof(Chapter));
while (reader.NodeType == XmlNodeType.Element)
Add((Chapter)ser.Deserialize(reader));
reader.ReadEndElement();
}
public void WriteXml(XmlWriter writer)
{
// Сериализуем дополнительные свойства вручную
writer.WriteStartElement(nameof(IsSelectedAll));
writer.WriteValue(IsSelectedAll);
writer.WriteEndElement();
// Сериализуем элементы коллекции
XmlSerializer ser = new XmlSerializer(typeof(Chapter));
foreach (var ch in this)
ser.Serialize(writer, ch);
}
}
Дополню ответ вариантом сериализации при композиции.
Наш класс коллекции превращается в такой:
public class ChapterCollection
{
public bool? IsSelectedAll { get; set; }
public ObservableCollection
Обратите внимание, создать экземпляр нужно обязательно вручную, сериализатор не может создавать "кастомные" коллекции, поэтому он не заполнит ее: = new ObservableCollection
Теперь вы можете использовать Linq, но придется указать имя этого свойства-коллекции:
myChapterCollection.Collection.Select(...);
Если вы реализуете IEnumerable<>, то сериализатор опять начнет думать что это коллекция и потеряет свойства, да еще к тому же потребует реализовать нетипизированный метод Add(object), что уже некрасиво и добавляет некоторую хрупкость.
PS: благодаря утиной типизации C# можно все же добавить маленький кусочек сахара, добавив в класс метод:
public IEnumerator
это хоть и не даст воспользоваться LINQ на экземпляре класса, но позволит упростить код foreach
// myChapterCollection.Collection писать не требуется:
foreach (var chapter in myChapterCollection)
...
Комментариев нет:
Отправить комментарий