Ошибка XmlSerializer Сериализация объектов интерфейса - PullRequest
1 голос
/ 10 января 2011

У меня есть список объектов, которые реализуют общий интерфейс.Если я пытаюсь просто сериализовать его, я получаю хорошее исключение, которое говорит мне, что сериализатор не может сериализовать интерфейсы:

private readonly ObservableCollection<ICanHasInterface> children = new ObservableCollection<ICanHasInterface>();
public ObservableCollection<ICanHasInterface> Children
{
    get { return children; }
}

=> "Невозможно сериализовать элемент ... типа ..., потому что это интерфейс"Видимо, запросить сериализатор получить тип объектов и пометить XmlElement атрибутом xsi:type (что делается, если объект наследуется от другого класса) - это слишком много.Поэтому, поскольку я не хочу реализовывать IXmlSerializable, я придумал обходной путь, который изначально выглядел многообещающе:

private readonly ObservableCollection<ICanHasInterface> children = new ObservableCollection<ICanHasInterface>();
[XmlIgnore()]
public ObservableCollection<ICanHasInterface> Children
{
    get { return children; }
}

[XmlElement("Child")]
public List<object> ChildrenSerialized
{
    get
    {
        return new List<object>(Children);
    }
    set
    {
        Children.Clear();
        foreach (var child in value)
        {
            if (child is ICanHasInterface) AddChild(child as ICanHasInterface);
        }
    }
}

С этим по крайней мере сериализация работает просто отлично (Примечание: либо укажите XmlInclude атрибуты длятипы, которые могут находиться в исходном списке или передать массив типов в конструкторе сериализатора), однако, если объект десериализован, коллекция Children заканчивается пустой, поскольку блок set никогда не достигается во время десериализации,Я совершенно не понимаю, почему это так;есть идеи?

1 Ответ

1 голос
/ 10 января 2011

При десериализации сериализатор использует ваш метод получения свойств для получения экземпляра коллекции, а затем вызывает Add () для каждого элемента. Он не вызывает ваш установщик свойств. Примерно так:

YourClass c = new YourClass();
c.ChildrenSerialized.Add(ReadValue());
...

Чтобы синхронизировать коллекции, вам нужно настроить поведение Add () для коллекции, которую вы возвращаете из метода получения свойства.

Лучшим вариантом является изменение свойства ChildrenSerialized для использования объекта []. Для массивов сериализатор считывает значение в массив и затем вызывает ваш установщик свойств со значением.

...