這篇隨筆對應的.Net命名空間是System.Xml.Serialization;文中的範例程式碼需要引用這個命名空間。
為什麼要做序列化和反序列化?
.Net程式執行時,物件都駐留在記憶體中;記憶體中的物件如果需要傳遞給其他系統使用;或者在關機時需要保存下來以便下次再次啟動程式使用就需要序列化和反序列化。
範圍:本文只介紹xml序列化,其實序列化可以是二進位的序列化,也可以是其他格式的序列化。
看一段最簡單的Xml序列化程式碼
#class Program { static void Main(string[] args) { int i = 10; //声明Xml序列化对象实例serializer XmlSerializer serializer = new XmlSerializer(typeof(int)); //执行序列化并将序列化结果输出到控制台 serializer.Serialize(Console.Out, i); Console.Read(); } }
上面程式碼對int i進行了序列化,並將序列化的結果輸出到了控制台,輸出結果如下
<?xml version="1.0" encoding="gb2312"?> <int>10</int>
可以將上述序列化的xml進行反序列化,如下程式碼
static void Main(string[] args) { using (StringReader rdr = new StringReader(@"<?xml version=""1.0"" encoding=""gb2312""?> <int>10</int>")) { //声明序列化对象实例serializer XmlSerializer serializer = new XmlSerializer(typeof(int)); //反序列化,并将反序列化结果值赋给变量i int i = (int)serializer.Deserialize(rdr); //输出反序列化结果 Console.WriteLine("i = " + i); Console.Read(); } }
以上程式碼用最簡單的方式說明了xml序列化和反序列化的過程,.Net系統類別庫為我們做了大量的工作,序列化和反序列化都非常簡單。但在現實中業務需求往往比較複雜,不可能只簡單的序列化一個int變量,顯示中我們需要對複雜型別進行可控制的序列化。
自訂物件的Xml序列化:
System.Xml.Serialization命名空間中有一系列的特性類,用來控制複雜型別序列化的控制。例如XmlElementAttribute、XmlAttributeAttribute、XmlArrayAttribute、XmlArrayItemAttribute、XmlRootAttribute等等。
看一個小例子,有一個自訂類別Cat,Cat類別有三個屬性分別為Color,Saying,Speed。
namespace UseXmlSerialization { class Program { static void Main(string[] args) { //声明一个猫咪对象 var c = new Cat { Color = "White", Speed = 10, Saying = "White or black, so long as the cat can catch mice, it is a good cat" }; //序列化这个对象 XmlSerializer serializer = new XmlSerializer(typeof(Cat)); //将对象序列化输出到控制台 serializer.Serialize(Console.Out, c); Console.Read(); } } [XmlRoot("cat")] public class Cat { //定义Color属性的序列化为cat节点的属性 [XmlAttribute("color")] public string Color { get; set; } //要求不序列化Speed属性 [XmlIgnore] public int Speed { get; set; } //设置Saying属性序列化为Xml子元素 [XmlElement("saying")] public string Saying { get; set; } } }
可以使用XmlElement指定屬性序列化為子節點(預設會序列化為子節點);或使用XmlAttribute特性制定屬性序列化為Xml節點的屬性;也可以透過XmlIgnore特性修飾要求序列化程序不序列化修飾屬性。
物件陣列的Xml序列化:
陣列的Xml序列化需要使用XmlArrayAttribute和XmlArrayItemAttribute;XmlArrayAttribute指定陣列元素的Xml節點名,XmlArrayItemAttribute指定陣列元素的Xml節點名。
如下程式碼範例:
/*玉开技术博客 http://www.php.cn/ */ using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Xml.Serialization; namespace UseXmlSerialization { class Program { static void Main(string[] args) { //声明一个猫咪对象 var cWhite = new Cat { Color = "White", Speed = 10, Saying = "White or black, so long as the cat can catch mice, it is a good cat" }; var cBlack = new Cat { Color = "Black", Speed = 10, Saying = "White or black, so long as the cat can catch mice, it is a good cat" }; CatCollection cc = new CatCollection { Cats = new Cat[] { cWhite,cBlack} }; //序列化这个对象 XmlSerializer serializer = new XmlSerializer(typeof(CatCollection)); //将对象序列化输出到控制台 serializer.Serialize(Console.Out, cc); Console.Read(); } } [XmlRoot("cats")] public class CatCollection { [XmlArray("items"),XmlArrayItem("item")] public Cat[] Cats { get; set; } } [XmlRoot("cat")] public class Cat { //定义Color属性的序列化为cat节点的属性 [XmlAttribute("color")] public string Color { get; set; } //要求不序列化Speed属性 [XmlIgnore] public int Speed { get; set; } //设置Saying属性序列化为Xml子元素 [XmlElement("saying")] public string Saying { get; set; } } }
以上程式碼將輸出:
<?xml version="1.0" encoding="gb2312"?> <cats xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://ww w.w3.org/2001/XMLSchema"> <items> <item color="White"> <saying>White or black, so long as the cat can catch mice, it is a good cat</saying> </item> <item color="Black"> <saying>White or black, so long as the cat can catch mice, it is a good cat</saying> </item> </items> </cats>
XmlSerializer記憶體洩漏問題:
多謝chenlulouis,仔細看了下msdn,確實存在洩漏的情況,msdn說明如下:
動態產生的組件
為了提高效能,XML 序列化基礎結構將動態產生組件,以序列化和反序列化指定類型。此基礎結構將會尋找並重複使用這些組件。此行為僅在使用下列建構子時發生:
XmlSerializer(Type)
XmlSerializer.XmlSerializer(Type, String)
如果使用任何其他建構函數,則會產生相同程式集的多個版本,且絕不會被卸載,這將導致記憶體洩漏和效能降低。最簡單的解決方案是使用先前提到的兩個建構函數的其中一個。否則,必須在 Hashtable 中快取組件,如以下範例所示。
也就是說我們在使用XmlSerializer序列化,初始化XmlSerializer物件時最好使用下面兩個建構子否則會造成記憶體洩漏。
XmlSerializer(Type)
XmlSerializer.XmlSerializer(Type, String)
#
以上是XmlSerializer 物件的Xml序列化和反序列化的範例程式碼分析的詳細內容。更多資訊請關注PHP中文網其他相關文章!