简体   繁体   English

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

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

I've got a base class which is compatible with XML serialization and a derived class which implements IXmlSerializable. 我有一个与XML序列化兼容的基类和一个实现IXmlSerializable的派生类。

In this example, the base class does implement 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 ());
        }
    }
}

This produces this output: 这会产生以下输出:

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

However, i'd like to use a base class which does not implement IXmlSerializable. 但是,我想使用一个实现IXmlSerializable的基类。 This prevents using base.Read/WriteXml . 这可以防止使用base.Read/WriteXml The result will be: 结果将是:

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

Is there any way to still get the desired result? 还有什么方法可以得到理想的结果吗?

Improving mtlung's answer, why don't you use XmlSerializer? 提高mtlung的答案,为什么不使用XmlSerializer? You can tune up your class with attribute so it can be serialized the way you want, and it's pretty simple to do. 您可以使用属性调整您的类,以便可以按照您希望的方式对其进行序列化,并且这很简单。

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()
    {
    }
}

Then, serializing and deserializing it would be pretty simple: 然后,序列化和反序列化将非常简单:

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);
    }
}

And the resulting XML would be something like this: 结果XML将是这样的:

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

This method works better with "POCO" classes, and it's simple and clean. 这种方法适用于“POCO”类,它简单而干净。 You don't even have to use the attributes, they are there to help you customize the serialization. 您甚至不必使用属性,它们可以帮助您自定义序列化。

" This prevents using base.Read/WriteXml." “这可以防止使用base.Read/WriteXml。”

Typically, if the base-class implemented IXmlSerializable , you might make it a virtual method so that the concrete version is used. 通常,如果基类实现了IXmlSerializable ,您可以将其设置为virtual方法,以便使用具体版本。 Typically, you'd also use explicit implementation (rather than public properties) - perhaps with some protected virtual methods for the implementation details (although keeping track of where the reader/writer is across different classes would be a nightmare). 通常,您还使用显式实现(而不是公共属性) - 可能使用一些protected virtual方法来实现详细信息(尽管跟踪读者/作者在不同类中的位置将是一场噩梦)。

AFAIK, there is no way to re-use XmlSerializer to write the base bits, while you add the derived bits. AFAIK,在添加派生位时,无法重用XmlSerializer来写入基本位。 IXmlSerializable is all-or-nothing. IXmlSerializable是全有或全无。

why not simply use XmlSerializer in your read/write function? 为什么不在您的读/写函数中简单地使用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