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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/527902/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-04 06:51:59  来源:igfitidea点击:

C# Xml-Serializing a derived class using IXmlSerializable

c#xmlserialization

提问by mafu

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 notimplement IXmlSerializable. This prevents using base.Read/WriteXml. The result will be:

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

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

Is there any way to still get the desired result?

有什么办法仍然可以获得所需的结果吗?

采纳答案by Marc Gravell

" This prevents using base.Read/WriteXml."

“这会阻止使用 base.Read/WriteXml。”

Typically, if the base-class implemented IXmlSerializable, you might make it a virtualmethod so that the concrete version is used. Typically, you'd also use explicit implementation (rather than public properties) - perhaps with some protected virtualmethods for the implementation details (although keeping track of where the reader/writer is across different classes would be a nightmare).

通常,如果基类实现了IXmlSerializable,您可以将其设为virtual方法,以便使用具体版本。通常,您还会使用显式实现(而不是公共属性)——也许使用一些protected virtual实现细节的方法(尽管跟踪读取器/写入器在不同类中的位置将是一场噩梦)。

AFAIK, there is no way to re-use XmlSerializerto write the basebits, while you add the derivedbits. IXmlSerializableis all-or-nothing.

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

回答by Ricky Lung

why not simply use XmlSerializer in your read/write function?

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

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

回答by Ricardo Nolde

Improving mtlung's answer, why don't you use 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.

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

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. You don't even have to use the attributes, they are there to help you customize the serialization.

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