C#XmlSerializer使用继承类的Order装饰器问题

时间:2014-02-19 11:48:52

标签: c# xml-serialization

此代码未提供建议的结果,因为元素的顺序未按指定显示:

using System;
using System.IO;
using System.Xml.Serialization;

namespace XmlSerializeTest
{
    class Program
    {
        static void Main(string[] args) {
            SubClass test = new SubClass();
            test.A = "A";
            test.B = "B";
            test.C = "C";

            XmlSerializer SerializerObj = new XmlSerializer(typeof(SubClass));
            TextWriter WriteFileStream = new StreamWriter(@"C:\test.xml");
            SerializerObj.Serialize(WriteFileStream, test);
            WriteFileStream.Close();
        }
    }

    [Serializable()]
    public class BaseClass {
        [XmlElement(Order = 2)]
        public string B { get; set; }
    } 

    [Serializable()]
    public class SubClass : BaseClass {
        [XmlElement(Order = 1)]
        public string A { get; set; }
        [XmlElement(Order = 3)]
        public string C { get; set; }
    } 
}

它给出了这个结果:

<BaseClass>
  <B>B</B>
  <A>A</A>
  <C>C</C>
</BaseClass>

如何获得正确的订单(A,B,C)?

我也试过这些替代方案:

new XmlSerializer(typeof(BaseClass), new [] {typeof(SubClass)});
new XmlSerializer(typeof(SubClass), new [] {typeof(BaseClass)});

2 个答案:

答案 0 :(得分:4)

默认的.NET DataContractSerializer按以下顺序序列化数据成员:

  • 基类层次结构(从上到下,即最后的类实例)
  • 按字母顺序排列没有订单属性的数据成员
  • 具有Order属性的数据成员(具有相同顺序的成员按字母顺序生成)

有关详细信息,请参阅MSDN

如果您需要不同的行为,则必须实现继承自XmlObjectSerializer的数据序列化程序。 - 看看这个post

修改/注意:
XmlSerializer和DataContractSerializer使用类似的顺序。除非你需要完全控制你的xml格式,否则我会使用DataContractSerializer。请参阅此blog post

答案 1 :(得分:0)

另一种方法是使用抽象属性,并将[XmlElement]属性附加到底层。因此,如果B在BaseClass中是抽象的,那么您可以使用[XmlElement]子类在SubClass中覆盖它。 BaseClass版本需要在其上放置[XmlIgnore]以避免重复。然后所有可序列化的属性都在SubClass中,它们将正确排序。 (如果你需要BaseClass也可以序列化,你可能需要提取一个公共超类,以便没有可序列化的类具有可序列化的子类。)