|
深入C#學(xué)習(xí)系列一:序列化(Serialize)、反序列化(Deserialize)
序列化又稱串行化,是.NET運行時環(huán)境用來支持用戶定義類型的流化的機制。其目的是以某種存儲形成使自定義對象持久化,或者將這種對象從一個地方傳輸?shù)搅硪粋€地方。
.NET框架提供了兩種串行化的方式:1、是使用BinaryFormatter進行串行化;2、使用SoapFormatter進行串行化;3、使用XmlSerializer進行串行化。第一種方式提供了一個簡單的二進制數(shù)據(jù)流以及某些附加的類型信息,而第二種將數(shù)據(jù)流格式化為XML存儲;第三種其實和第二種差不多也是XML的格式存儲,只不過比第二種的XML格式要簡化很多(去掉了SOAP特有的額外信息)。 可以使用[Serializable]屬性將類標(biāo)志為可序列化的。如果某個類的元素不想被序列化,1、2可以使用[NonSerialized]屬性來標(biāo)志,2、可以使用[XmlIgnore]來標(biāo)志。 1、使用BinaryFormatter進行串行化 下面是一個可串行化的類: using System; using System.Data; using System.Configuration; using System.Web; using System.Web.Security; using System.Web.UI; using System.Web.UI.WebControls; using System.Web.UI.WebControls.WebParts; using System.Web.UI.HtmlControls; using System.IO; using System.Runtime.Serialization.Formatters.Binary;![]() /**//// <summary> /// ClassToSerialize 的摘要說明 /// </summary> [Serializable] public class ClassToSerialize![]() ![]() { public int id = 100; public string name = "Name"; [NonSerialized] public string Sex = "男"; }![]() 下面是串行化和反串行化的方法: public void SerializeNow()![]() { ClassToSerialize c = new ClassToSerialize(); FileStream fileStream = new FileStream("c:\\temp.dat", FileMode.Create); BinaryFormatter b = new BinaryFormatter(); b.Serialize(fileStream, c); fileStream.Close(); } public void DeSerializeNow()![]() { ClassToSerialize c = new ClassToSerialize(); c.Sex = "kkkk"; FileStream fileStream = new FileStream("c:\\temp.dat", FileMode.Open, FileAccess.Read, FileShare.Read); BinaryFormatter b = new BinaryFormatter(); c = b.Deserialize(fileStream) as ClassToSerialize;Response.Write(c.name); Response.Write(c.Sex); fileStream.Close(); }調(diào)用上述兩個方法就可以看到串行化的結(jié)果:Sex屬性因為被標(biāo)志為[NonSerialized],故其值總是為null。 2、使用SoapFormatter進行串行化 和BinaryFormatter類似,我們只需要做一下簡單修改即可: a.將using語句中的.Formatter.Binary改為.Formatter.Soap; b.將所有的BinaryFormatter替換為SoapFormatter. c.確保報存文件的擴展名為.xml 經(jīng)過上面簡單改動,即可實現(xiàn)SoapFormatter的串行化,這時候產(chǎn)生的文件就是一個xml格式的文件。 3、使用XmlSerializer進行串行化 關(guān)于格式化器還有一個問題,假設(shè)我們需要XML,但是不想要SOAP特有的額外信息,那么我們應(yīng)該怎么辦呢?有兩中方案:要么編寫一個實現(xiàn)IFormatter接口的類,采用的方式類似于SoapFormatter類,但是沒有你不需要的信息;要么使用庫類XmlSerializer,這個類不使用Serializable屬性,但是它提供了類似的功能。 如果我們不想使用主流的串行化機制,而想使用XmlSeralizer進行串行化我們需要做一下修改: a.添加System.Xml.Serialization命名空間。 b.Serializable和NoSerialized屬性將被忽略,而是使用XmlIgnore屬性,它的行為與NoSerialized類似。 c.XmlSeralizer要求類有個默認的構(gòu)造器,這個條件可能已經(jīng)滿足了。 下面看示例: 要序列化的類: using System; using System.Data; using System.Configuration; using System.Web; using System.Web.Security; using System.Web.UI; using System.Web.UI.WebControls; using System.Web.UI.WebControls.WebParts; using System.Web.UI.HtmlControls; using System.Xml.Serialization; [Serializable] public class Person![]() ![]() { private string name; public string Name![]() { get![]() { return name; } set![]() { name = value; } }![]() ![]() public string Sex; public int Age = 31; public Course[] Courses;![]() public Person()![]() { } public Person(string Name)![]() { name = Name; Sex = "男"; } } [Serializable] public class Course![]() ![]() { public string Name; [XmlIgnore] public string Description; public Course()![]() { } public Course(string name, string description)![]() { Name = name; Description = description; } } ![]() 序列化和反序列化方法: public void XMLSerialize()![]() { Person c = new Person("cyj"); c.Courses = new Course[2]; c.Courses[0] = new Course("英語", "交流工具"); c.Courses[1] = new Course("數(shù)學(xué)","自然科學(xué)"); XmlSerializer xs = new XmlSerializer(typeof(Person)); Stream stream = new FileStream("c:\\cyj.XML",FileMode.Create,FileAccess.Write,FileShare.Read); xs.Serialize(stream,c); stream.Close(); } public void XMLDeserialize()![]() { XmlSerializer xs = new XmlSerializer(typeof(Person)); Stream stream = new FileStream("C:\\cyj.XML",FileMode.Open,FileAccess.Read,FileShare.Read); Person p = xs.Deserialize(stream) as Person; Response.Write(p.Name); Response.Write(p.Age.ToString()); Response.Write(p.Courses[0].Name); Response.Write(p.Courses[0].Description); Response.Write(p.Courses[1].Name); Response.Write(p.Courses[1].Description); stream.Close(); }這里Course類的Description屬性值將始終為null,生成的xml文檔中也沒有該節(jié)點,如下圖: <?xml version="1.0"?> <Person xmlns:xsi="http://www./2001/XMLSchema-instance" xmlns:xsd="http://www./2001/XMLSchema"> <Sex>男</Sex> <Age>31</Age> <Courses> <Course> <Name>英語</Name> <Description>交流工具</Description> </Course> <Course> <Name>數(shù)學(xué)</Name> <Description>自然科學(xué)</Description> </Course> </Courses> <Name>cyj</Name> </Person>4、自定義序列化 如果你希望讓用戶對類進行串行化,但是對數(shù)據(jù)流的組織方式不完全滿意,那么可以通過在自定義類中實現(xiàn)接口來自定義串行化行為。這個接口只有一個方法,GetObjectData. 這個方法用于將對類對象進行串行化所需要的數(shù)據(jù)填進SerializationInfo對象。你使用的格式化器將構(gòu)造SerializationInfo對象,然后在串行化時調(diào)用GetObjectData. 如果類的父類也實現(xiàn)了ISerializable,那么應(yīng)該調(diào)用GetObjectData的父類實現(xiàn)。 如果你實現(xiàn)了ISerializable,那么還必須提供一個具有特定原型的構(gòu)造器,這個構(gòu)造器的參數(shù)列表必須與GetObjectData相同。這個構(gòu)造器應(yīng)該被聲明為私有的或受保護的,以防止粗心的開發(fā)人員直接使用它。 示例如下: 實現(xiàn)ISerializable的類: using System; using System.Data; using System.Configuration; using System.Web; using System.Web.Security; using System.Web.UI; using System.Web.UI.WebControls; using System.Web.UI.WebControls.WebParts; using System.Web.UI.HtmlControls; using System.Runtime.Serialization; using System.Runtime.Serialization.Formatters.Binary;![]() /**//// <summary> /// Employee 的摘要說明 /// </summary> [Serializable] public class Employee:ISerializable![]() ![]() { public int EmpId=100; public string EmpName="劉德華"; [NonSerialized] public string NoSerialString = "NoSerialString-Test"; public Employee()![]() { // // TODO: 在此處添加構(gòu)造函數(shù)邏輯 // } private Employee(SerializationInfo info, StreamingContext ctxt)![]() { EmpId = (int)info.GetValue("EmployeeId", typeof(int)); EmpName = (String)info.GetValue("EmployeeName",typeof(string)); //NoSerialString = (String)info.GetValue("EmployeeString",typeof(string)); } public void GetObjectData(SerializationInfo info, StreamingContext ctxt)![]() { info.AddValue("EmployeeId", EmpId); info.AddValue("EmployeeName", EmpName); //info.AddValue("EmployeeString", NoSerialString); } }![]() 序列化和反序列化方法: public void OtherEmployeeClassTest()![]() { Employee mp = new Employee(); mp.EmpId = 10; mp.EmpName = "邱楓"; mp.NoSerialString = "你好呀"; Stream steam = File.Open("c:\\temp3.dat", FileMode.Create); BinaryFormatter bf = new BinaryFormatter(); Response.Write("Writing Employee Info:"); bf.Serialize(steam,mp); steam.Close(); mp = null; //反序列化 Stream steam2 = File.Open("c:\\temp3.dat", FileMode.Open); BinaryFormatter bf2 = new BinaryFormatter(); Response.Write("Reading Employee Info:"); Employee mp2 = (Employee)bf2.Deserialize(steam2); steam2.Close(); Response.Write(mp2.EmpId); Response.Write(mp2.EmpName); Response.Write(mp2.NoSerialString); } |
|
|
來自: franklinfj > 《vs》