使用父标记序列化基类的列表

本文关键字:列表 基类 序列化 | 更新日期: 2023-09-27 18:33:44

我似乎能够在网上找到试图避免这种行为的人,但我似乎无法得到我想要的行为。

我有一个动物列表,我想为每个动物类型使用不同的标签对它们进行序列化(而不是带有附加属性的默认 beahviour)

为了获得这种行为,我使用以下代码

    [XmlElementAttribute(Order = 4)]
    [XmlElement("Frog", typeof(Frog))]
    [XmlElement("Cat", typeof(Cat))]
    [XmlElement("Dog", typeof(Dog))]
    public List<Animal> lines = new List<Animal>();

这很好用,除了它扁平化了列表,如果 xml 输出更像,我更喜欢它 <animals> <Dog>Bob</Dog> <Cat>Fred</Cat> <Dog>Mike</Dog> </animals>保留<animals>标签

使用父标记序列化基类的列表<T>

更改[XmlArrayAttribute(Order=4)][XmlElementAttribute(Order = 4)]

您还可以在属性中指定一个ElementName参数,该参数将是根名称,即:[XmlArrayAttribute(Order=4, ElementName="animals")]

*注意:Order=4 是这种情况的特殊情况。你通常不需要它。*

编辑:(感谢OP评论):

您还必须将属于列表的对象类的属性从[XmlElement]更改为[XmlArrayItem](此处为 MSDN 文档),如下所示:

[XmlArrayItem("Frog", typeof(Frog))]
[XmlArrayItem("Cat", typeof(Cat))]
[XmlArrayItem("Dog", typeof(Dog))]

您始终可以将列表包装在其自己的类中,您将获得所需的 XML:

public class StackOverflow_10524470
{
    public class Animal
    {
        [XmlText]
        public string Name { get; set; }
    }
    public class Dog : Animal { }
    public class Cat : Animal { }
    public class Frog : Animal { }
    public class Root
    {
        [XmlElementAttribute(Order = 4, ElementName = "animals")]
        public Animals animals;
    }
    public class Animals
    {
        [XmlElementAttribute(Order = 4)]
        [XmlElement("Frog", typeof(Frog))]
        [XmlElement("Cat", typeof(Cat))]
        [XmlElement("Dog", typeof(Dog))]
        public List<Animal> lines = new List<Animal>();
    }
    public static void Test()
    {
        MemoryStream ms = new MemoryStream();
        XmlSerializer xs = new XmlSerializer(typeof(Root));
        Root root = new Root
        {
            animals = new Animals
            {
                lines = new List<Animal> 
                { 
                    new Dog { Name = "Fido" },
                    new Cat { Name = "Fluffy" },
                    new Frog { Name = "Singer" },
                }
            }
        };
        xs.Serialize(ms, root);
        Console.WriteLine(Encoding.UTF8.GetString(ms.ToArray()));
    }
}