2009-10-11 4 views
1

У меня есть массив элементов, которые мне нужно сериализовать с помощью XmlSerializer. Проблема, с которой я сталкиваюсь, состоит в том, что у меня есть 2 производных класса и их сериализация, поэтому они имеют имя элемента общей базы, похоже, не работают.XML-сериализация производных классов

Итак, это то, как XML должен выглядеть:

<Root> 
    <Base> foo </Base> 
</Root> 

Вместо этого, я получаю

<Root> 
    <Derived1> foo </Derived1> 
</Root> 

Код для массива элементов я сериализации является

private object[] m_nodes; 

[System.Xml.Serialization.XmlElementAttribute("Base", typeof(Derived1)] 
[System.Xml.Serialization.XmlElementAttribute("Base", typeof(Derived2)] 

public object[] Nodes 
{ 
    get 
    { 
     return this.m_nodes; 
    } 
    set 
    { 
     this.m_nodes = value; 
    } 
} 

С приведенным выше кодом, я понимаю, что есть ошибка отражения с узлами. Если я изменю «Base» в обоих XmlEelementAttributes к «Derived1» и Derived2" , она работает, но имя элемента является неправильным.

[System.Xml.Serialization.XmlInclude(typeof(Derived1))] 
public abstract class Base 
{ 
    public Base() 
    { 

    } 
} 



[System.SerializableAttribute()] 
[System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true)] 
public class Derived1: Base 
{ 
    public Derived1() 
    { 

    } 
} 

Любая помощь очень ценится. Спасибо так много.

ответ

5

XML, Сериализация включает в себя как сериализацию, так и процедуру десериализации. Поэтому, если вам действительно удалось это сделать, сериализатор не сможет определить, какой тип использовать при десериализации результирующей структуры XML. По моему опыту лучше использовать либо два разных имени, либо используйте собственный сериализатор/десериализатор, используя классы XmlWriter и XmlReader.

1

Ответ Дэвида правильный. Это невозможно с помощью простой XmlSerialization, поскольку он не может определить, какой из производных классов должен быть создан при десериализации из содержимого элемента XML.

Если можно использовать два разных имени, это сработает. Они не должны быть тем же именем, что и производные классы, вам просто нужно дать XmlSerialization ключ для определения того, что есть.

Пользовательские сериализации с помощью XmlReader/Writer всегда возможно, но это требует больше времени, чем просто XmlSerialization (особенно, если вы не опытный XML наркоман!)

Что делать в таких случаях является создание промежуточную иерархию классов и писать простые преобразования в коде. Таким образом, исходные объекты сначала преобразуются в промежуточную структуру, которая может обрабатываться XmlSerialization.

Например, в вашем случае вы можете создать класс, аналогичный Base (я его называю BaseSerializable), и заполнить данные Derived1 и Derived2. BaseSerializable может обрабатываться XmlSerialization. При десериализации вы получаете BaseSerializable из XmlSerialization, а затем определяете (используя контент полей/свойств), который должен быть создан экземплярами классов Derived1/Derived2. Таким образом, на практике вы кодируете очень небольшую часть сериализации с помощью своего собственного кода и оставляете остальные в библиотеке XmlSerialization.

+0

Спасибо. Ответы твои и Давида теперь имеют смысл, и я смотрю на это с точки зрения необходимости и десериализации.Я думаю, что я предположил, что существует какой-то способ указать, что, поскольку некоторый атрибут = «Derived1» в XML, я мог бы вручную указать, какой объект создать. – mfanto

0

После долгих поисков альтернативы, я нашел следующее сообщение здесь на переполнение стека: How do I use an XmlSerializer to deserialize an object that might be of a base or derived class without knowing the type beforehand?

Я попробовал его и он работает, а также для сериализации. Поэтому при сериализации это также дает хороший результат. Для массива вам необходимо использовать атрибут XmlArrayItem.

Смежные вопросы