序列化多态List BUT无法更改类型定义

时间:2018-06-10 00:58:39

标签: c# serialization

我正在使用另一方的DLL,它定义了动物,猫,鱼类。

//Begin another party's DLL
public class animals
{
}

public class cat : animals
{
    public string size { get; set; }
    public string furColor { get; set; }
}

public class fish : animals
{
    public string size { get; set; }
    public string scaleColor { get; set; }
}
//End another party's DLL

static void Main(string[] args)
{

    using (var xmlWriter = XmlWriter.Create("a.xml", new XmlWriterSettings { Indent = true }))
    {
        var eventArgsList = new List<animals>();
        eventArgsList.Add(new cat { size = "10", furColor = "red" });
        eventArgsList.Add(new fish { size = "20", scaleColor = "blue" });

        new XmlSerializer(eventArgsList.GetType(),new[] { typeof(cat), typeof(fish) }).Serialize(xmlWriter, eventArgsList);
    }
}

以上代码正确输出

<?xml version="1.0" encoding="utf-8"?>
<ArrayOfAnimals xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
  <animals xsi:type="cat">
    <size>10</size>
    <furColor>red</furColor>
  </animals>
  <animals xsi:type="fish">
    <size>20</size>
    <scaleColor>blue</scaleColor>
  </animals>
</ArrayOfAnimals>

但是,我希望它看起来像

<?xml version="1.0" encoding="utf-8"?>
<Animals xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
  <cat>
    <size>10</size>
    <furColor>red</furColor>
  </cat>
  <fish>
    <size>20</size>
    <scaleColor>blue</scaleColor>
  </fish>
</Animals>

这与Serialize a polymorphic List with the same type name类似,但我无法更改类型定义。我想我必须使用XmlAttributeOverrides,有人可以告诉我该怎么做吗?

2 个答案:

答案 0 :(得分:1)

为了在不编写自定义序列化程序的情况下使用XML结构,您需要在C#类中使用相同的结构。但这很容易,因为Visual Studio会为您完成此任务。

复制所需的XML和create classes for that XML structure。它将创建以下类。您需要进行一次调整并设置AnonymousType = false,如下所示。

/// <remarks/>
[System.Xml.Serialization.XmlTypeAttribute(AnonymousType = false)]
[System.Xml.Serialization.XmlRootAttribute(Namespace = "", IsNullable = false)]
public partial class Animals
{

    private AnimalsCat[] catField;

    private AnimalsFish[] fishField;

    /// <remarks/>
    [System.Xml.Serialization.XmlElementAttribute("cat")]
    public AnimalsCat[] cat
    {
        get
        {
            return this.catField;
        }
        set
        {
            this.catField = value;
        }
    }

    /// <remarks/>
    [System.Xml.Serialization.XmlElementAttribute("fish")]
    public AnimalsFish[] fish
    {
        get
        {
            return this.fishField;
        }
        set
        {
            this.fishField = value;
        }
    }
}

/// <remarks/>
[System.Xml.Serialization.XmlTypeAttribute(AnonymousType = false)]
public partial class AnimalsCat
{

    private byte sizeField;

    private string furColorField;

    /// <remarks/>
    public byte size
    {
        get
        {
            return this.sizeField;
        }
        set
        {
            this.sizeField = value;
        }
    }

    /// <remarks/>
    public string furColor
    {
        get
        {
            return this.furColorField;
        }
        set
        {
            this.furColorField = value;
        }
    }
}

/// <remarks/>
[System.Xml.Serialization.XmlTypeAttribute(AnonymousType = false)]
public partial class AnimalsFish
{

    private byte sizeField;

    private string scaleColorField;

    /// <remarks/>
    public byte size
    {
        get
        {
            return this.sizeField;
        }
        set
        {
            this.sizeField = value;
        }
    }

    /// <remarks/>
    public string scaleColor
    {
        get
        {
            return this.scaleColorField;
        }
        set
        {
            this.scaleColorField = value;
        }
    }
}

<强>用法

using (var xmlWriter = XmlWriter.Create("a.xml", new XmlWriterSettings { Indent = true }))
{
    var eventArgsList = new Animals();
    eventArgsList.cat = new AnimalsCat[1]; // set this based on the number 
    eventArgsList.fish = new AnimalsFish[2]; // set this based on the number 

    // Do this using a loop but I just hard coded it
    eventArgsList.cat[0] = new AnimalsCat { size = 10, furColor = "red" };
    eventArgsList.fish[0] = new AnimalsFish { size = 20, scaleColor = "blue" };
    eventArgsList.fish[1] = new AnimalsFish { size = 30, scaleColor = "orange" };

    new XmlSerializer(eventArgsList.GetType(), new[] { typeof(AnimalsCat), typeof(AnimalsFish) }).Serialize(xmlWriter, eventArgsList);
}

<强>输出

<?xml version="1.0" encoding="utf-8"?>
<Animals xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
  <cat>
    <size>10</size>
    <furColor>red</furColor>
  </cat>
  <fish>
    <size>20</size>
    <scaleColor>blue</scaleColor>
  </fish>
  <fish>
    <size>30</size>
    <scaleColor>orange</scaleColor>
  </fish>
</Animals>

答案 1 :(得分:0)

受CodingYoshi创新方式的启发,我发现以下助手类的工作时间缩短了100行。

[XmlRoot("Animals")]
public class AnimalsHelper
{
    [XmlElement("Cat", typeof(cat))]
    [XmlElement("Fish", typeof(fish))]
    public List<animals> Animals { get; set; } = new List<animals>();
}

static void Main(string[] args)
{

    using (var xmlWriter = XmlWriter.Create("a.xml", new XmlWriterSettings { Indent = true }))
    {
        var animalsHelper= new AnimalsHelper();
        animalsHelper.Animals.Add(new cat { size = "10", furColor = "red" });
        animalsHelper.Animals.Add(new fish { size = "20", scaleColor = "blue" });

        new XmlSerializer(animalsHelper.GetType(),new[] { typeof(cat), typeof(fish) }).Serialize(xmlWriter, animalsHelper);
    }

    using (var xmlReader = XmlReader.Create("a.xml", new XmlReaderSettings { IgnoreWhitespace = true }))
    {
        var obj = (AnimalsHelper)new XmlSerializer(animalsHelper.GetType(), new[] { typeof(cat), typeof(fish) }).Deserialize(xmlReader);

    }
}

我一直在寻求一种不使用辅助类的解决方案。