C 中Serializable序列化

2021-07-06 06:16:34 字數 4091 閱讀 9986

序列化就是是將物件轉換為容易傳輸的格式的過程,一般情況下轉化打流檔案,放入記憶體或者io檔案 中。例如,可以序列化乙個物件,然後使用 http 通過 internet 在客戶端和伺服器之間傳輸該物件,或者和其它應用程式共享使用。反之,反序列化根據流重新構造物件。 

一、幾種序列化技術

1)二進位制序列化保持型別保真度,這對於在應用程式的不同呼叫之間保留物件的狀態很有用。例如,通過將物件序列化到剪貼簿,可在不同的應用程式之間共享物件。您可以將物件序列化到流、磁碟、記憶體和網路等等。遠端處理使用序列化「通過值」在計算機或應用程式域之間傳遞物件。

2)xml 序列化僅序列化公共屬性和字段,且不保持型別保真度。當您要提供或使用資料而不限制使用該資料的應用程式時,這一點是很有用的。由於 xml 是乙個開放式標準,因此,對於通過 web 共享資料而言,這是乙個很好的選擇。soap 同樣是乙個開放式標準,這使它也成為乙個頗具吸引力的選擇。

3)使用提供的資料協定,將型別例項序列化和反序列化為 xml 流或文件(或者json格式)。常應用於wcf通訊。 

二、序列化分類

1、基本序列化

要使乙個類可序列化,最簡單的方法是使用 serializable 屬性對它進行標記,如下所示

複製**

**如下:

[serializable]

public class myobject

將上面的類的乙個例項序列化為乙個檔案

複製**

**如下:

myobject obj = new myobject();

obj.n1 = 1;

obj.n2 = 24;

obj.str = "一些字串";

iformatter formatter = new binaryformatter();

stream stream = new filestream("myfile.bin", filemode.create,

fileaccess.write, fileshare.none);

formatter.serialize(stream, obj);

stream.close();

上面例項的反序列化

複製**

**如下:

iformatter formatter = new binaryformatter();

stream stream = new filestream("myfile。bin", filemode.open,

fileaccess.read, fileshare.read);

myobject obj = (myobject) formatter.deserialize(fromstream);

stream.close();

如果要求具有可移植性,請使用 soapformatter。所要做的更改只是將以上**中的格式化程式換成 soapformatter,而 serialize 和 deserialize 呼叫不變。

需要注意的是,無法繼承 serializable 屬性。如果從 myobject 派生出乙個新的類,則這個新的類也必須使用該屬性進行標記,否則將無法序列化。例如,如果試圖序列化以下類例項,將會顯示乙個 serializationexception,說明 mystuff 型別未標記為可序列化。

2、選擇性序列化

類通常包含不應被序列化的字段。例如,假設某個類用乙個成員變數來儲存執行緒 id。當此類被反序列化時,序列化此類時所儲存的 id 對應的執行緒可能不再執行,所以對這個值進行序列化沒有意義。可以通過使用 nonserialized 屬性標記成員變數來防止它們被序列化,如下所示:

複製**

**如下:

[serializable]

public class myobject

3、自定義序列化

可以通過在物件上實現 iserializable 介面來自定義序列化過程。這一功能在反序列化後成員變數的值失效時尤其有用,但是需要為變數提供值以重建物件的完整狀態。要實現 iserializable,需要實現 getobjectdata 方法以及乙個特殊的建構函式,在反序列化物件時要用到此建構函式。以下**示例說明了如何在前一部分中提到的 myobject 類上實現 iserializable。

複製**

**如下:

[serializable]

public class myobject : iserializable

protected myobject(serializationinfo info, streamingcontext context)

public virtual void getobjectdata(serializationinfo info,

streamingcontext context)

}在序列化過程中呼叫 getobjectdata 時,需要填充方法呼叫中提供的 serializationinfo 物件。只需按名稱/值對的形式新增將要序列化的變數。其名稱可以是任何文字。只要已序列化的資料足以在反序列化過程中還原物件,便可以自由選擇新增至 serializationinfo 的成員變數。如果基物件實現了 iserializable,則派生類應呼叫其基物件的 getobjectdata 方法。

需要強調的是,將 iserializable 新增至某個類時,需要同時實現 getobjectdata 以及特殊的建構函式。如果缺少 getobjectdata,編譯器將發出警告。但是,由於無法強制實現建構函式,所以,缺少建構函式時不會發出警告。如果在沒有建構函式的情況下嘗試反序列化某個類,將會出現異常。在消除潛在安全性和版本控制問題等方面,當前設計優於 setobjectdata 方法。例如,如果將 setobjectdata 方法定義為某個介面的一部分,則此方法必須是公共方法,這使得使用者不得不編寫**來防止多次呼叫 setobjectdata 方法。可以想象,如果某個物件正在執行某些操作,而某個惡意應用程式卻呼叫此物件的 setobjectdata 方法,將會引起一些潛在的麻煩。

在反序列化過程中,使用出於此目的而提供的建構函式將 serializationinfo 傳遞給類。物件反序列化時,對建構函式的任何可見性約束都將被忽略,因此,可以將類標記為 public、protected、internal或 private。乙個不錯的辦法是,在類未封裝的情況下,將建構函式標記為 protect。如果類已封裝,則應標記為 private。要還原物件的狀態,只需使用序列化時採用的名稱,從 serializationinfo 中檢索變數的值。如果基類實現了 iserializable,則應呼叫基類的建構函式,以使基礎物件可以還原其變數。

如果從實現了 iserializable 的類派生出乙個新的類,則只要新的類中含有任何需要序列化的變數,就必須同時實現建構函式以及 getobjectdata 方法。以下**片段顯示了如何使用上文所示的 myobject 類來完成此操作。

複製**

**如下:

[serializable]

public class objecttwo : myobject

protected objecttwo(serializationinfo si, streamingcontext context) :

base(si,context)

public override void getobjectdata(serializationinfo si,

streamingcontext context)

}切記要在反序列化建構函式中呼叫基類,否則,將永遠不會呼叫基類上的建構函式,並且在反序列化後也無法構建完整的物件。  在反序列化過程中檢索關鍵字/值對非常容易,但是,由於無法保證從雜湊表派生出的類已反序列化,所以把這些物件新增回雜湊表時會出現一些問題。因此,建議目前不要在雜湊表上呼叫方法。

三、如果物件的狀態需要在不同版本間發生改變的方法

1、實現 iserializable。這使您可以精確地控制序列化和反序列化過程,在反序列化過程中正確地新增和解釋未來狀態。

2、使用 nonserialized 屬性標記不重要的成員變數。僅當預計類在不同版本間的變化較小時,才可使用這個選項。例如,把乙個新變數新增至類的較高版本後,可以將該變數標記為 nonserialized,以確保該類與早期版本保持相容。

Serializable在C 中的作用

system.serializableattribute 序列化是指儲存和獲取磁碟檔案 記憶體或其他地方中的物件。在序列化時,所有的例項資料都儲存到 儲存介質上,在取消序列化時,物件會被還原,且不能與其原例項區別開來。只需給類新增 serializable 屬性,就可以實現序列化例項的成員。並行化是...

C 中的 序列化 Serializable 理解

我的理解 比如用乙個類描述一張合同,而這個類例項化後其中的字段儲存著合同的資訊,如果現在要把這個類的例項傳送到另一台機器 另乙個窗體或是想儲存這個類以便以後再取出來用 持久化物件 可以對這個類進行序列化 序列化實際上是乙個資訊流 傳送或儲存,用的時候再反序列化重新生成這個物件 為什麼您想要使用序列化...

C 中的 序列化 Serializable 理解

為什麼您想要使用序列化?有兩個最重要的原因促使對序列化的使用 乙個原因是將物件的狀態保持在儲存 中,以便可以在以後重新建立精確的副本 另乙個原因是通過值將物件從乙個應用程式域傳送到另乙個應用程式域中。例如,序列化可用於在 asp.net 中儲存會話狀態並將物件複製到 windows 窗體的剪貼簿中。...