Проблема ObservableCollection<T> Deserialize

200
21 апреля 2018, 16:50

Не могу разобраться с проблемой десериализации колекции объектов.

Продолжение темы XMLSerializer Десериализация двух элементов в один список

Прошлый вариант помог, объект стал десериализоваться, однако все же необходимо не обычный массив, а именно observablecollection

При попытке изменить свойства на данный тип, происходит падение NullReferenceException Провозился весь день, но так и не понял из-за чего. Поиск по интернету не навел меня на мысль. Последняя надежда на вас.

Код десериализуемого объекта:

[Serializable]
[XmlRoot("icons", Namespace = "interfaces.xsd")]
public class RibbonInterface : Notifier
{
    public ObservableCollection<Icon> _Icons;
    [XmlElement("small", typeof(Icon))]
    [XmlElement("large", typeof(Icon))]
    [XmlChoiceIdentifier("ItemsElementName")]
    public ObservableCollection<Icon> Icons
    {
        get
        {
            return _Icons;
        }
        set
        {
            Set(ref _Icons, value, "Icons");
        }
    }
    [XmlIgnore]
    public ItemChoiceType[] ItemsElementName
    {
        get;
        set;
    }
}
public enum ItemChoiceType
{
    small,
    large
}

Начало десериализации выглядит так:

var xmlDoc = new XmlDocument();
xmlDoc.Load(ofd.FileName);
var ns = new XmlNamespaceManager(xmlDoc.NameTable);
ns.AddNamespace("ws", "interfaces.xsd");
var xmlReader = xmlDoc.SelectSingleNode("ws:template/ws:icons", ns).CreateNavigator().ReadSubtree();
var serializer = new XmlSerializer(typeof(RibbonInterface));
Model.InterfaceImages = (RibbonInterface)serializer.Deserialize(xmlReader);

Падение происходит на строке var serializer = new XmlSerializer(typeof(RibbonInterface)); Т.е. до самого построения объекта даже не дошли. Где-то проблема с описанием десериализуемого объекта.

На всякий случай класс Notifier

public class Notifier : INotifyPropertyChanged
{
    public event PropertyChangedEventHandler PropertyChanged;
    public void NotifyPropertyChanged(string Name)
    {
        if (string.IsNullOrEmpty(Name))
            throw new ArgumentNullException("Name не может быть NULL или пустым");
        if (PropertyChanged != null)
        {
            PropertyChanged(this, new PropertyChangedEventArgs(Name));
        }
    }
    public void Set(ref ObservableCollection<Icon> Property, ObservableCollection<Icon> Value, string Name)
    {
        if (Property != Value)
        {
            Property = Value;
            NotifyPropertyChanged(Name);
        }
    }
}
Answer 1

Проблема, судя по всему, в том, что вы хотите сериализовать UI-объект. UI-объекты не предназначены для сериализации.

Говоря более широко, невозможно сериализовать класс, который не было создан для сериализации. Для корректной сериализации в классе не должно быть интерфейсов, непубличных полей/свойств, должен быть конструктор без параметров, класс должен быть доступен как public и т. п. Не стоит надеяться, что произвольный чужой класс будет подходить для этого.

Ну и не стоит пытаться натянуть сову на глобус пытаться сломать семантику своего класса, убрав параметры из конструктора и сделав все поля публичными только для того, чтобы его можно было сериализовать.

Вместо этого лучше всего написать DTO-класс, не содержащий логики, и сериализовать его.

А UI-объекты вообще лучше не сериализовать, в рамках MVVM нужно серализовать модельные объекты, и строить из них VM, и соответственно и UI.

READ ALSO
Не сложная программа для разметки с языком css [требует правки]

Не сложная программа для разметки с языком css [требует правки]

Нужно что-нибудь не сложное по типу Lazarus

251
Подсветка текущего пункта меню

Подсветка текущего пункта меню

Задача стоит в том чтобы текущий пункт меню подсвечивая, но что-то не работает

240
Почему в CHROME не отображается видео mp4?

Почему в CHROME не отображается видео mp4?

Добавляю на страницу два видео mp4 формата через html5 тегОдно работает, а второе только звук

305
Валидация поля регулярным выражения

Валидация поля регулярным выражения

Номер заказа имеет форму:

212