XML Serialize общий список сериализуемых объектов с абстрактным базовым классом - PullRequest
7 голосов
/ 12 февраля 2012

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

Ответы [ 2 ]

12 голосов
/ 02 марта 2012

Другой альтернативой является использование 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>
5 голосов
/ 12 февраля 2012

Часто бывает полезно иметь абстрактные классы с несколькими производными типами, чтобы разрешить использование строго типизированных списков и тому подобное.

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

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

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

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

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

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

<DocumentFragment xsi:type="TextDocumentFragment">

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

...