2009-02-09 94 views
6

我有一个与XML序列化和实现IXmlSerializable的派生类兼容的基类。C#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 /> 

有什么办法仍然可以得到理想的结果吗?

回答

2

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

通常情况下,如果基类实现了IXmlSerializable,那么可以使其成为virtual方法,以便使用具体的版本。通常情况下,你也可以使用显式实现(而不是公共属性) - 也许有一些protected virtual方法的实现细节(尽管跟踪读者/作者在不同类中的位置将是一场噩梦)。

据我所知,没有办法再使用XmlSerializer基地位,而在添加衍生位。 IXmlSerializable是全有或全无。

+0

来自Java和它的死容易序列化,我有点难过听到这一点。我实际上创建了基类,我很幸运地可以访问它,实现IXmlSerializable。它有效,但它有点痛,因为我正在编写不应该存在的代码。 – mafu 2009-02-09 17:00:15

+0

除非有人想出一个新的方法,这是正式的答案。 – mafu 2009-02-10 14:54:03

1

为什么不简单地在你的读/写功能中使用XmlSerializer?

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

改善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” 工作得更好类,它很简单,干净。您甚至不必使用这些属性,它们可以帮助您自定义序列化。