【问题标题】:XML Serialize generic list of serializable objects with abstract base classXML序列化具有抽象基类的可序列化对象的通用列表
【发布时间】:2012-02-12 06:51:00
【问题描述】:

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

【问题讨论】:

标签: c# .net xml-serialization


【解决方案1】:

另一种选择是使用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>

【讨论】:

  • 如果你不想保留 Animals 元素,你可以使用 XmlArrayItemAttribute。
【解决方案2】:

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

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

任何特定于派生类的附加属性也将使用此方法包含在内。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2010-11-15
    • 1970-01-01
    • 2016-01-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-05-22
    • 1970-01-01
    相关资源
    最近更新 更多