.net序列化及反序列化
序列化是指一個對象的實例可以被保存,保存成一個二進制串,當然,一旦被保存成二進制串,那么也可以保存成文本串了。
比如,一個計數器,數值為2,我們可以用字符串“2”表示。
如果有個對象,叫做connter,當前值為2,那么可以序列化成“2”,反向的,也可以從“2”得到值為2的計數器實例。
這樣,關機時序列化它,開機時反序列化它,每次開機都是延續的。不會都是從頭開始。
序列化概念的提出和實現,可以使我們的應用程序的設置信息保存和讀取更加方便。
序列化有很多好處,比如,在一台機器上產生一個實例,初始化完畢,然后可以序列化,通過網絡傳送到另一台機器,然后反序列化,得到對象實例,之后再執行某些業務邏輯,得到結果,再序列化,返回第一台機器,第一台機器得到對象實例,得到結果。
這個例子是目前比較先進的“智能代理”的原理。
當前比較熱火的web services使用soap協議,soap協議也是以對象的可序列化為基礎的。
“序列化”可被定義為將對象的狀態存儲到存儲媒介中的過程。在此過程中,對象的公共字段和私有字段以及類的名稱(包括包含該類的程序集)都被轉換為字節流,然后寫入數據流。在以后“反序列化”該對象時,創建原始對象的精確復本。
一、為什么要選擇序列化
一個原因是將對象的狀態保持在存儲媒體中,以便可以在以后重新創建精確的副本;
另一個原因是通過值將對象從一個應用程序域發送到另一個應用程序域中。
例如,序列化可用於在 ASP.NET 中保存會話狀態並將對象復制到 Windows 窗體的剪貼板中。遠程處理還可以使用序列化通過值將對象從一個應用程序域傳遞到另一個應用程序域中。
二、如何實現對象的序列化及反序列化
要實現對象的序列化,首先要保證該對象可以序列化。而且,序列化只是將對象的屬性進行有效的保存,對於對象的一些方法則無法實現序列化的。
實現一個類可序列化的最簡便的方法就是增加Serializable屬性標記類。如:
[Serializable()]
public class MEABlock
{
private int m_ID;
public string Caption;
public MEABlock()
{
///構造函數
}
}
即可實現該類的可序列化。
要將該類的實例序列化為到文件中?.NET FrameWork提供了兩種方法:
1、XML序列化
使用 XmLSerializer 類,可將下列項序列化。
- 公共類的公共讀/寫屬性和字段
- 實現 ICollection 或 IEnumerable 的類。(注意只有集合會被序列化,而公共屬性卻不會。)
- XmlElement 對象。
- XmlNode 對象。
- DataSet 對象。
要實現上述類的實例的序列化,可參照如下例子:
MEABlock myBlock = new MEABlock();
// Insert code to set properties and fields of the object.
XmlSerializer mySerializer = new XmlSerializer(typeof(MEABlock));
// To write to a file, create a StreamWriter object.
StreamWriter myWriter = new StreamWriter("myFileName.xml");
mySerializer.Serialize(myWriter, MEABlock);
需要注意的是XML序列化只會將public的字段保存,對於私有字段不予於保存。
生成的XML文件格式如下:
<MEABlock>
<Caption>Test</Caption>
</MEABlock>
對於對象的反序列化,則如下:
MEABlock myBlock;
// Constructs an instance of the XmlSerializer with the type
// of object that is being deserialized.
XmlSerializer mySerializer = new XmlSerializer(typeof(MEABlock));
// To read the file, creates a FileStream.
FileStream myFileStream = new FileStream("myFileName.xml", FileMode.Open);
// Calls the Deserialize method and casts to the object type.
myBlock = (MEABlock)mySerializer.Deserialize(myFileStream)
2、二進制序列化
與XML序列化不同的是,二進制序列化可以將類的實例中所有字段(包括私有和公有)都進行序列化操作。這就更方便、更准確的還原了對象的副本。
要實現上述類的實例的序列化,可參照如下例子:
MEABlock myBlock = new MEABlock();
// Insert code to set properties and fields of the object.
IFormatter formatter = new BinaryFormatter();
Stream stream = new FileStream("MyFile.bin",FileMode.Create,FileAccess.Write, FileShare.None);
formatter.Serialize(stream, myBlock);
stream.Close();
對於對象的反序列化,則如下:
IFormatter formatter = new BinaryFormatter();
Stream stream = new FileStream("MyFile.bin", FileMode.Open,FileAccess.Read, FileShare.Read);
MEABlock myBlock = (MEABlock) formatter.Deserialize(stream);
stream.Close();
三、如何變相實現自定義可視化控件的序列化、反序列化
對於WinForm中自定義控件,由於繼承於System.Windows.Form類,而Form類又是從MarshalByRefObject繼承的,窗體本身無法做到序列化,窗體的實現基於Win32下GUI資源,不能脫離當前上下文存在。
當然可以采用變通的方法實現控件的序列化。這里采用的是記憶類模型。
定義記憶類(其實就是一個可序列化的實體類)用於記錄控件的有效屬性,需要序列化控件的時候,只需要將該控件的實例Copy到記憶類,演變成序列化保存該記憶類的操作。
反序列化是一個逆過程。將數據流反序列化成為該記憶類,再根據該記憶類的屬性生成控件實例。而對於控件的一些事件、方法則可以繼續使用。