http://blog.csdn.net/chinarenkai/article/details/3220452
如果你做遠程方法調用(RPC)時,比如,服務器端有個類A及對象a,客戶端需要無視網絡的存在,直接調用對象a。這種情況下,就需要把類A設計為可序列化的,那么它的實例a也就可以實例化了。
說得簡單點,在服務器的 命名空間中的對象a,肯定不能直接被客戶端的命名空間中的一個對象調用,這不可能,對吧。
但是如果你把服務器的對象a中的特征屬性(不一定是所有屬性)變成xml,傳送到客戶端,然后客戶端用你給的特征屬性可以模擬的生成一個對象a。
這個過程就是 rpc,而要把對象a變成xml,就是序列化,反之,把xml變成模擬對象a就是反序列化。
以上是rpc中的序列化。
實際使用中,把app關閉的時候,內存對象可以通過序列化,可以變成可以保存的xml,這樣,以便下次app再開得時候,把以前保存過的xml(或者txt等)反序列化成對象。
一句話,序列化就是把內存中對象以一種可以保存的形式保存起來。
需要注意的是:
序列化可以制定序列化整個類,或者 類的某些屬性。
你是想數據持久化嗎?
首先,如果Rectangle是你自定義的類的話,必須保證這個類里面的所有狀態都是可以儲存的,並且要有[Serializable()]標識.
然后你可以用 XmlSerializer類或者 BinaryFormatter類將其逐一序列化.序列化后。
可以將其序列化成XML存進數據庫也可以序列化成2進制保存.
==========================
首先,你想保存某個類中的數據,那這個類最好是個實體類,
比如
[Serializable]
[XmlRoot("Rectangle")] public class Rectangle{ //fields here. ... public Rectangele(){...} [XmlElement("Width")] public int Width{get;set;} [XmlElement("Length")] public int Length{get;set;} }
像這樣的類被選擇序列化才比較有意義,它要求必須有一個無參數的構造函數.
經過類似下面的方法序列化后,將獲得一個文件流
Rectangle rec = new Rectangle{Width = 5,Length = 6}; using (FileStream fs = new FileStream(fileFullName, FileMode.Create, FileAccess.Write, FileShare.Read)) { XmlSerializer xs = new XmlSerializer(rec.GetType()); //序列化成Xml文件. xs.Serialize(fs, rec); //使用文件流 ... }
同樣可以序列化成 2進制文件流.:
using (FileStream fs = new FileStream(fileFullName, FileMode.Open, FileAccess.ReadWrite)) { BinaryFormatter bf = new BinaryFormatter(); bf.Serialize(fs, rec); }
另外,如果你的類用來記錄狀態,比如是否跟遠程主機連接成功,之類的,那么序列化是沒有意義的.因為當你反序列化的時候,他的環境已經變了,而以前保存的狀態已經不穩定了.
序列化,是記錄類中所有可序列化的信息.並可以還原.
另外一個選擇呢,就是只記錄內容,用內容重新實例化類:
比如
Rectangle rec = new Rectangle{Width = 5,Length = 6};
rec 你只需要在數據庫中記錄Width = 5,Length = 6
在將來,你可以根據 Width,Length的值重新實例化Rectangle類.
至於集合,可類推.
選擇性序列化
類通常包含不應被序列化的字段。例如,假設某個類用一個成員變量來存儲線程 ID。當此類被反序列化時,序列化此類時所存儲的 ID 對應的線程可能不再運行,所以對這個值進行序列化沒有意義。可以通過使用 NonSerialized 屬性標記成員變量來防止它們被序列化,如下所示:
[Serializable]
public class MyObject { public int n1; [NonSerialized] public int n2; public String str; }
自定義序列化
可以通過在對象上實現 ISerializable 接口來自定義序列化過程。這一功能在反序列化后成員變量的值失效時尤其有用,但是需要為變量提供值以重建對象的完整狀態。要實現 ISerializable,需要實現 GetObjectData方法以及一個特殊的構造函數,在反序列化對象時要用到此構造函數。以下代碼示例說明了如何在前一部分中提到的 MyObject 類上實現 ISerializable。
[Serializable]
public class MyObject : ISerializable { public int n1; public int n2; public String str; public MyObject() { } protected MyObject(SerializationInfo info, StreamingContext context) { n1 = info.GetInt32("i"); n2 = info.GetInt32("j"); str = info.GetString("k"); } public virtual void GetObjectData(SerializationInfo info, StreamingContext context) { info.AddValue("i", n1); info.AddValue("j", n2); info.AddValue("k", str); } }
在序列化過程中調用 GetObjectData 時,需要填充方法調用中提供的 SerializationInfo 對象。只需按名稱/值對的形式添加將要序列化的變量。其名稱可以是任何文本。只要已序列化的數據足以在反序列化過程中還原對象,便可以自由選擇添加至 SerializationInfo 的成員變量。如果基對象實現了 ISerializable,則派生類應調用其基對象的 GetObjectData 方法。
需要強調的是,將 ISerializable 添加至某個類時,需要同時實現 GetObjectData 以及特殊的構造函數。如果缺少 GetObjectData,編譯器將發出警告。但是,由於無法強制實現構造函數,所以,缺少構造函數時不會發出警告。如果在沒有構造函數的情況下嘗試反序列化某個類,將會出現異常。在消除潛在安全性和版本控制問題等方面,當前設計優於 SetObjectData 方法。例如,如果將 SetObjectData 方法定義為某個接口的一部分,則此方法必須是公共方法,這使得用戶不得不編寫代碼來防止多次調用 SetObjectData 方法。可以想象,如果某個對象正在執行某些操作,而某個惡意應用程序卻調用此對象的 SetObjectData 方法,將會引起一些潛在的麻煩。