標籤:應用程式 private public .net 記錄
一直想寫這個專題,但是工作後人很懶散,總下不了決心,今天一個人在家就寫下來。
關於序列化,可以總結出它的作用有以下幾點:
1.記錄應用程式的狀態,在下次啟動時還原上次的狀態。
2.進程之間的通訊,如使用socket編程時使用。這裡的進程包括同一台主機之間進程的通訊,也包括不同主機之間的通訊。
3.作為對象的深拷貝的一種實現方式。
.net中的序列化支援下面幾種序列化機制:
1.使可序列化的類型序列化和還原序列化
2.控制可序列化的類型的序列化/還原序列化內容和過程
3.將類型序列化/還原序列化為不同的類型
4.使用代理序列化/還原序列化原本不可序列化的類型
要想一個類型可序列化,只需要在定義這個類型時為它加上一個[Serializable]特性既可,如下:
[Serializable]public class ClassA{ private float x; private float y; [NonSerialized] private float area; }
這樣,類型A即支援序列化了。.net序列化規則有如下特點:枚舉和委託自動支援序列化,序列化特性不支援繼承,因此如果在定義另一個類B繼承ClassA時,不顯示為類B加上序列化特性,那麼類B是不支援序列化的,即[Serializable]支援繼承,然而[NonSerialized]特性不支援繼承,該特性標識類中不想被序列化的欄位。
如何控制序列化、還原序列化的過程。在類中的相關方法上加上[OnSerializing],[OnSerialized],[OnDeserializing],[OnDesirialized]特性用於控制類型在序列化之前,序列化之後,反序列之前,還原序列化之後要做的工作。
那麼序列化器如何進行一個類型的具體序列化過程呢?經msdn介紹及相關資料查詢得知,這個過程藉助於System.Runtime.Serialization.FormatterServices這個類型,具體步驟如下:
(1)擷取類型的序列化欄位,標識了[NonSerialized]特性的欄位除外。這個過程通過調用
FormatterServices類型的GetSerializableMembers方法完成。
(2)擷取類型需要序列化的欄位的值。調用FormaterServices類型的GetObjectData方法完成。
(3)寫入程式集的標識和類型的完整標識。
(4)寫入步驟2擷取的值到流中,完成序列化過程。
還原序列化的具體步驟:
(1)根據序列化進流中的程式集標識和類型標識,建立還原序列化類型的Type,調用GetTypeFromAssembly
方法完成
(2)根據獲得的Type調用GetUnitializedObject方法建立還原序列化的對象,這個過程不通過構造器完成,所有欄位全部被初始化為0或null.
(3)獲得類型的序列化欄位集合。
(4)根據流中的欄位值構造欄位值的集合。
(5)調用PopulateObjectMembers設定建立的對象的值。
如何精細控制序列化、還原序列化的內容呢?比如我們想序列化這個類型時不只是簡單的的序列化那些欄位的值,而是這個基於欄位值的一個函數值,怎麼實現呢?通過實現介面ISerializable來完成。
interface ISerializable{ void GetObjectData(SerializationInfo info,StreamingContext context)}
在GetObjectData方法中添加任何我們想要序列化的內容。一般來說,除實現這個介面外,我們還需要實現一個特殊的構造器,這個構造器用於在還原序列化時設定類型的欄位值。由於這兩個函數的特殊性,它們設計是被序列化器使用的,為了避免其他人的濫用,最好使用下面的特性
[SecurityPermissionAttribute(SecurityAction.Demond,SerializationFormatter=true)]
序列化器在序列化一個類型時如果發現類型實現了改介面,則會忽略應用與欄位的特性值,改為調用該介面的GetObjectData方法,設定實際需要序列化的值。
將對象序列化為不同的類型或者將對象還原序列化不同的類型,該怎麼實現呢?一般來說,我們讓該對象實現ISerializable介面,在GetObjectData方法中通過調用SerializationInfo的SetType設定新的對象即可,而這個對象實現IObjectReference介面。
上面這些序列化技術都是在我們能修改類型的原始碼的情況下進行的,那麼當我們不能修改類型的原始碼或者這個類型開始並沒有設計為可序列化時,我們想序列化它怎麼辦?通過.NET提供的序列化代理技術可以解決這個問題,序列化代理必須實現那面這個介面:
interface ISerializationSurrogate{ void SetObjectData(object obj,SerializationInfo info,StreamingContext context); void GetObjectData(object obj,SerializationInfo info,StreamingContext context); }
GetObjectData方法用於設定你想序列化的資料,obj為你想序列化的類型,SetObjectData為還原序列化時調用的方法,在這裡你可以進行對類型進行初始化。至於使用代理的具體步驟,查詢MSDN吧!
本文出自 “電腦課餘愛好者” 部落格,請務必保留此出處http://19910822.blog.51cto.com/2072697/1534312