天天看點

.NET(C#):XML序列化時派生類的處理1. 針對基類的XmlSerializer序列化派生類2. 類内成員是派生類的序列化

目錄

<a href="http://www.cnblogs.com/mgen/archive/2011/12/03/2275014.html#_h1">1. 針對基類的XmlSerializer序列化派生類</a>

<a href="http://www.cnblogs.com/mgen/archive/2011/12/03/2275014.html#_h2">2. 類内成員是派生類的序列化</a>

注意:

運作代碼請注意添加如下命名空間:

using System.Xml;

using System.Xml.Serialization;

using System.IO;

<a href="http://www.cnblogs.com/mgen/archive/2011/12/03/2275014.html#_hContent">傳回目錄</a>

派生類将會序列化成這樣的XML:

&lt;基類名稱xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

         xmlns:xsd="http://www.w3.org/2001/XMLSchema"

         xsi:type="派生類名稱"&gt;

    &lt;!-- 基類和派生類的内容 --&gt;

&lt;/基類名稱&gt;

第一種方法是在基類添加XmlInclude特性,這樣的話基類的XmlSerializer可以序列化派生類了。

代碼:

//基類加入XmlInclude

[XmlInclude(typeof(b))]

publicclassa

{

    publicint aaa;

}

publicclassb : a

    publicint bbb;

classProgram

    staticvoid Main()

    {

        var xs =newXmlSerializer(typeof(a));

        using (var textWriter =newStringWriter())

        {

            xs.Serialize(textWriter, newb());

            Console.WriteLine(textWriter);

        }

    }

輸出XML:

&lt;axmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

   xmlns:xsd="http://www.w3.org/2001/XMLSchema"

   xsi:type="b"&gt;

    &lt;aaa&gt;0&lt;/aaa&gt;

    &lt;bbb&gt;0&lt;/bbb&gt;

&lt;/a&gt;

第二種方法就是在XmlSerializer的構造函數内指定派生類型,然後序列化,這樣就不用在基類上加入XmlInclude特性了。

//無需加入XmlInclude

        var xs =newXmlSerializer(typeof(a), newType[] { typeof(b) });

輸出和上面一樣!

還是上面的類a和b,現在再加入一個c類,這個c類中有一個a的對象:

publicclassc

    publica objA =newa();

此時直接XML序列化一個c對象,結果是這樣的XML:

&lt;cxmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

   xmlns:xsd="http://www.w3.org/2001/XMLSchema"&gt;

    &lt;objA&gt;

        &lt;aaa&gt;0&lt;/aaa&gt;

    &lt;/objA&gt;

&lt;/c&gt;

下面搞得複雜些,把c中的a對象改成這樣:

    publica objA =newb();

此時仿佛又回到了文章第一個标題,如果直接序列化c的話,會抛出異常。那麼按照上面第一個方法,先在a上加入XmlInclude特性,然後再序列化c對象。

全部代碼:

        var xs =newXmlSerializer(typeof(c));

            xs.Serialize(textWriter, newc());

輸出XML(根節點c省略):

&lt;objAxsi:type="b"&gt;

&lt;/objA&gt;

和标題1的第一個方法類似!

但是标題1的第二個方法在這裡沒法使用的,因為c類和b類沒有任何繼承關系,在針對c的XmlSerializer不可能加入b的類型。這裡其實還 有一種方法,加入XmlElement特性,其中ElementName屬性是最終的Xml元素名稱,而Type屬性是針對的類型,這裡加入b類型,不過 最好把a類型也加入(因為字段類型是a,有可能被指派為a的對象)。

//不需要加XmlInclude

    [XmlElement(ElementName ="b", Type =typeof(b))]

    [XmlElement(ElementName ="a", Type =typeof(a))]

生成XML:

    &lt;b&gt;

        &lt;bbb&gt;0&lt;/bbb&gt;

    &lt;/b&gt;