繁体   English   中英

C#Xml-使用IXmlSerializable对派生类进行序列化

[英]C# Xml-Serializing a derived class using IXmlSerializable

我有一个与XML序列化兼容的基类和一个实现IXmlSerializable的派生类。

在此示例中,基类确实实现了IXmlSerializable:


using System.Diagnostics;
using System.Text;
using System.Xml;
using System.Xml.Schema;
using System.Xml.Serialization;

namespace XmlSerializationDerived
{
    public class Foo
    {
        public int fooProp;

        public XmlSchema GetSchema()
        {
            return null;
        }

        public void ReadXml(XmlReader reader)
        {
            fooProp = int.Parse (reader.ReadElementString ("fooProp"));
        }

        public void WriteXml(XmlWriter writer)
        {
            writer.WriteElementString ("fooProp", fooProp.ToString ());
        }
    }

    public class Bar : Foo, IXmlSerializable
    {
        public new void ReadXml(XmlReader reader)
        {
            base.ReadXml (reader);
        }

        public new void WriteXml(XmlWriter writer)
        {
            base.WriteXml (writer);
        }

        static void Main(string[] args)
        {
            StringBuilder sb = new StringBuilder ();
            XmlWriter writer = XmlWriter.Create (sb);

            Bar bar = new Bar ();
            bar.fooProp = 42;

            XmlSerializer serializer = new XmlSerializer (typeof (Bar));
            serializer.Serialize (writer, bar);

            Debug.WriteLine (sb.ToString ());
        }
    }
}

这会产生以下输出:

<?xml version="1.0" encoding="utf-16"?><Bar><fooProp>42</fooProp></Bar>

但是,我想使用一个实现IXmlSerializable的基类。 这可以防止使用base.Read/WriteXml 结果将是:

<?xml version="1.0" encoding="utf-16"?><Bar />

还有什么方法可以得到理想的结果吗?

提高mtlung的答案,为什么不使用XmlSerializer? 您可以使用属性调整您的类,以便可以按照您希望的方式对其进行序列化,并且这很简单。

using System.Xml.Serialization;

...

[XmlRoot("someclass")]
public class SomeClass
{
    [XmlAttribute("p01")]
    public int MyProperty01
    {
        get { ... }
    }

    [XmlArray("sometypes")]
    public SomeType[] MyProperty02
    {
        get { ... }
    }

    [XmlText]
    public int MyProperty03
    {
        get { ... }
    }

    public SomeClass()
    {
    }
}

然后,序列化和反序列化将非常简单:

void Save(SomeClass obj)
{
    XmlSerializer xs = new XmlSerializer(typeof(SomeClass));
    using (FileStream fs = new FileStream("c:\\test.xml", ...))
    {
        xs.Serialize(fs, obj);
    }
}

void Load(out SomeClass obj)
{
    XmlSerializer xs = new XmlSerializer(typeof(SomeClass));
    using (FileStream fs = new FileStream("c:\\test.xml", ...))
    {
        obj = xs.Deserialize(fs);
    }
}

结果XML将是这样的:

<someclass p01="...">
  <sometype>
    <!-- SomeType serialized objects as child elements -->
  </sometype>
  # value of "MyProperty03" as text #
</someclass>

这种方法适用于“POCO”类,它简单而干净。 您甚至不必使用属性,它们可以帮助您自定义序列化。

“这可以防止使用base.Read/WriteXml。”

通常,如果基类实现了IXmlSerializable ,您可以将其设置为virtual方法,以便使用具体版本。 通常,您还使用显式实现(而不是公共属性) - 可能使用一些protected virtual方法来实现详细信息(尽管跟踪读者/作者在不同类中的位置将是一场噩梦)。

AFAIK,在添加派生位时,无法重用XmlSerializer来写入基本位。 IXmlSerializable是全有或全无。

为什么不在您的读/写函数中简单地使用XmlSerializer?

XmlSerializer s = new XmlSerializer(typeof(Foo));
s.Serialize(writer, base);

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM