2012-02-12 3 views
6

Любой хороший пример того, как сериализовать список общих объектов с абстрактным базовым классом. Образцы с не абстрактным базовым классом перечислены в XML Serialize generic list of serializable objects. Мой базовый класс похож на Microsoft.Build.Utilities.TaskXML Сериализовать общий список сериализуемых объектов с абстрактным базовым классом

+0

Согласен с @Dmitry. Альтернативный ответ можно найти в разделе Сериализация без XmlInclude http://stackoverflow.com/questions/370291/serializing-without-xmlinclude – walter

ответ

4

Часто бывает полезно иметь абстрактные классы с несколькими производными типами, позволяющие использовать строго типизированные списки и такие.

Например, у вас может быть класс DocumentFragment, который является абстрактным и двумя конкретными классами, называемыми TextDocumentFragment и CommentDocumentFragment (этот пример из Willis).

Это позволяет создать свойство List, которое может содержать объекты только этих двух типов.

При попытке создать WebService, который возвращает этот список, вы получите сообщение об ошибке, но это легко обойти на код ниже ....

[Serializable()] 
[System.Xml.Serialization.XmlInclude(typeof(TextDocumentFragment))] 
[System.Xml.Serialization.XmlInclude(typeof(CommentDocumentFragment))] 
public abstract class DocumentFragment { 
...} 

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

Это генерирует атрибут в элементе DocumentFragment, определяющий фактический тип, как показано ниже.

<DocumentFragment xsi:type="TextDocumentFragment"> 

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

11

Другой альтернативой является использование XmlElementAttribute, чтобы переместить список известных типов в самом общий список ...

using System; 
using System.Xml; 
using System.Xml.Serialization; 
using System.Collections.Generic; 

public abstract class Animal 
{ 
    public int Weight { get; set; }  
} 

public class Cat : Animal 
{ 
    public int FurLength { get; set; }  
} 

public class Fish : Animal 
{ 
    public int ScalesCount { get; set; }  
} 

public class AnimalFarm 
{ 
    [XmlElement(typeof(Cat))] 
    [XmlElement(typeof(Fish))] 
    public List<Animal> Animals { get; set; } 

    public AnimalFarm() 
    { 
     Animals = new List<Animal>(); 
    } 
} 

public class Program 
{ 
    public static void Main() 
    { 
     AnimalFarm animalFarm = new AnimalFarm(); 
     animalFarm.Animals.Add(new Cat() { Weight = 4000, FurLength = 3 }); 
     animalFarm.Animals.Add(new Fish() { Weight = 200, ScalesCount = 99 }); 
     XmlSerializer serializer = new XmlSerializer(typeof(AnimalFarm)); 
     serializer.Serialize(Console.Out, animalFarm); 
    } 
} 

... что также приведет к лучше выглядящим вывод XML (без уродливого xsi:type)

<?xml version="1.0" encoding="ibm850"?> 
<AnimalFarm xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema"> 
    <Cat> 
    <Weight>4000</Weight> 
    <FurLength>3</FurLength> 
    </Cat> 
    <Fish> 
    <Weight>200</Weight> 
    <ScalesCount>99</ScalesCount> 
    </Fish> 
</AnimalFarm> 
+0

, если вы не сохранили элемент Animals, вместо этого вы можете использовать XmlArrayItemAttribute. – Console

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