2009-02-09 90 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」 工作得更好類,它很簡單,乾淨。您甚至不必使用這些屬性,它們可以幫助您自定義序列化。