NET中物件序列化方法

才智咖 人氣:9.32K
NET中物件序列化方法
 摘  要  實現序列化最重要的兩個原因是:將物件的狀態儲存在儲存媒體中以便以後重新創建出完全相同的副本;按值將物件從一個應用程式域傳送至另一個應用程式域。例如,序列化可用於在 中儲存會話狀態;將物件複製到 Windows 窗體的剪貼簿中;它還可用於按值將物件從一個應用程式域遠端傳遞至另一個應用程式域。本文簡要介紹了 Microsoft 中使用的序列化。     關鍵詞  ;序列化;封送 
1  引言     序列化是指將物件例項的狀態儲存到儲存媒體的過程。在此過程中,先將物件的公共欄位和私有欄位以及類的名稱(包括類所在的程式集)轉換為位元組流,然後再把位元組流寫入資料流。在隨後對物件進行反序列化時,將創建出與原物件完全相同的副本。     在物件導向的環境中實現序列化機制時,必須在易用性和靈活性之間進行一些權衡。只要對此過程有足夠的控制能力,就可以使該過程在很大程度上自動進行。例如,簡單的二進位制序列化不能滿足需要,或者,由於特定原因需要確定類中哪些欄位需要序列化。以下各部分將探討 框架提供的可靠的序列化機制,並著重介紹如何根據需要自定義序列化過程。2  持久儲存     我們經常需要將物件的欄位值儲存到磁碟中,並在以後在記憶體中還原次物件。儘管不使用序列化也能完成這項工作,但這種方法通常很繁瑣而且容易出錯,並且在需要跟蹤物件的層次結構時,會變得越來越複雜。可以想象一下編寫包含大量物件的大型業務應用程式的情形,程式設計師不得不為每一個物件編寫程式碼,以便將欄位和屬性儲存至磁碟以及從磁碟還原這些欄位和屬性。序列化提供了輕鬆實現這個目標的快捷方法。     公共語言執行時 (CLR) 管理物件在記憶體中的分佈, 框架則通過使用反射提供自動的序列化機制。物件序列化後,類的名稱、程式集以及類例項的所有資料成員均被寫入儲存媒體中。物件通常用成員變數來儲存對其它例項的引用。類序列化後,序列化引擎將跟蹤所有已序列化的引用物件,以確保同一物件不被序列化多次。 框架所提供的序列化體系結構可以自動正確處理物件圖表和迴圈引用。對物件圖表的惟一要求是,由正在進行序列化的物件所引用的所有物件都必須標記為 Serializable。否則,當序列化程式試圖序列化未標記的物件時將會出現異常。當反序列化已序列化的類時,將重新建立該類的物件,並自動還原所有資料成員的值。3  按值封送     按值封送是指將物件序列化為位元組流,並從一個應用程式域傳輸至另一個應用程式域,然後進行反序列化,從而在第二個應用程式域中產生出該物件的一個副本,這在COM技術中經常提到。在中,物件僅在建立物件的應用程式域中有效,除非物件是從 MarshalByRefObject 派生得到或標記為 Serializable,否則,任何將物件作為引數傳遞或作為結果返回到另外一個應用程式域都將失敗。     如果物件標記為 Serializable,則該物件將被自動序列化,並從一個應用程式域傳輸至另一個應用程式域,然後進行反序列化,從而在第二個應用程式域中產生出該物件的一個精確副本。如果物件是從 MarshalByRefObject 派生得到,則從一個應用程式域傳遞至另一個應用程式域的是物件引用,而不是物件本身。也可以將從 MarshalByRefObject 派生得到的物件標記為 Serializable。遠端使用此物件時,負責進行序列化並已預先配置為 SurrogateSelector 的格式化程式將控制序列化過程,並用一個代理替換所有從 MarshalByRefObject 派生得到的物件。如果沒有預先配置為 SurrogateSelector,序列化體系結構將遵從下面的標準序列化規則。4  基本序列化     要使一個類可序列化,最簡單的方法是使用 Serializable 屬性對它進行標記,如下所示:[Serializable]public class MyObject{public int n1 = 0;public int n2 = 0;public String str = null;}以下程式碼片段說明了如何將此類的一個例項序列化為一個檔案:MyObject obj = new MyObject();obj.n1 = 1;obj.n2 = 24; = "一些字串";IFormatter formatter = new BinaryFormatter();Stream stream = new FileStream("",te,e,);alize(stream,obj);e();     本例使用二進位制格式化程式進行序列化。只需建立一個要使用的流和格式化程式的例項,然後呼叫格式化程式的 Serialize 方法。流和要序列化的物件例項作為引數提供給此呼叫。類中包括 private 變數的所有成員變數,都將被序列化,但這一點在本例中未明確體現出來。在這一點上,二進位制序列化不同於只序列化公共欄位的 XML 序列化程式。     將物件還原到它以前的狀態也非常容易。首先,建立格式化程式和流以進行讀取,然後讓格式化程式對物件進行反序列化。以下程式碼片段說明了如何進行此操作。IFormatter formatter = new BinaryFormatter();Stream stream = new FileStream("",,,);MyObject obj = (MyObject) rialize(fromStream);e();// 下面是證明eLine("n1:{0}",obj.n1);eLine("n2:{0}",obj.n2);eLine("str:{0}",);     上面所使用的 BinaryFormatter 效率很高,能生成非常緊湊的位元組流。所有使用此格式化程式序列化的物件也可使用它進行反序列化,對於序列化將在 平臺上進行反序列化的物件,此格式化程式是一個理想的工具。需要注意的是,對物件進行反序列化時並不呼叫建構函式。對反序列化新增這項約束,是出於效能方面的'考慮。但是,這違反了物件編寫者通常採用的一些執行時約定,因此,開發人員在將物件標記為可序列化時,應確保考慮了這一特殊約定。
TAGS:序列化 NET