XML使用抽象基类序列化可序列化对象的通用列表

时间:2012-02-12 06:51:00

标签: c# .net xml-serialization

关于如何使用抽象基类序列化通用对象列表的任何好示例。具有非抽象基类的样本列在XML Serialize generic list of serializable objects中。我的基类类似于Microsoft.Build.Utilities.Task

2 个答案:

答案 0 :(得分:12)

另一种方法是使用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>

答案 1 :(得分:5)

使用具有多个派生类型的抽象类通常很有用,以允许使用强类型列表等。

例如,您可能有一个抽象的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">

使用此方法也将包含特定于派生类的任何其他属性。