目錄
<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:
<基類名稱xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xsi:type="派生類名稱">
<!-- 基類和派生類的内容 -->
</基類名稱>
第一種方法是在基類添加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:
<axmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xsi:type="b">
<aaa>0</aaa>
<bbb>0</bbb>
</a>
第二種方法就是在XmlSerializer的構造函數内指定派生類型,然後序列化,這樣就不用在基類上加入XmlInclude特性了。
//無需加入XmlInclude
var xs =newXmlSerializer(typeof(a), newType[] { typeof(b) });
輸出和上面一樣!
還是上面的類a和b,現在再加入一個c類,這個c類中有一個a的對象:
publicclassc
publica objA =newa();
此時直接XML序列化一個c對象,結果是這樣的XML:
<cxmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<objA>
<aaa>0</aaa>
</objA>
</c>
下面搞得複雜些,把c中的a對象改成這樣:
publica objA =newb();
此時仿佛又回到了文章第一個标題,如果直接序列化c的話,會抛出異常。那麼按照上面第一個方法,先在a上加入XmlInclude特性,然後再序列化c對象。
全部代碼:
var xs =newXmlSerializer(typeof(c));
xs.Serialize(textWriter, newc());
輸出XML(根節點c省略):
<objAxsi:type="b">
</objA>
和标題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:
<b>
<bbb>0</bbb>
</b>