Serialization/Deserialization Quick Start
序列化是將一個對象以及相關的對象轉換成字節流的過程;反序列化就是序列化的逆過程; System.Runtime.Serialization命名空間; 當序列化一個對象時,Formatter首先抓取程序集標識,并確定程序集通過調用System.Reflection.Assembly.Load()被裝載到執行的AppDomain中; 程序集被裝載后,Formatter在程序集中查找待反序列化對象所匹配的類型,然后實例化再根據流來初始化實例的字段; 一些擴展程序使用Assembly.LoadFrom()來加載程序集,然后從定義在程序集中的類型來構造對象。這些對象在序列化時沒有問題,但是反序列化時,Formatter會嘗試使用Assembly.Load()來加載程序集,大多數情況下,CLR不能準確定位程序集文件,所以可能會引發SerializationException; 因為上面的原因,如果使用Assembly.LoadFrom()來加載程序集,那么強烈建議在反序列化之前處理System.AppDomain.AssemblyResolver事件。 Making a Type Serializable
對象在默認情況下是不能序列化的,可以通過給類型加上[Serializable]標簽來實現; [Serializable]屬性不能被子類型所繼承; System.Object有[Serializable]屬性; 一般來說,推薦大多數類型為可序列化的?(我的看法是那些可能會被跨邊界訪問的類型)。 Controlling Serialization and Deserialization
至少有兩個原因使得你不打算讓類型實例的一些字段被序列化: - 字段的值在反序列化時已經失效了,比如Windows Kernel對象的句柄(文件、進程、線程、互斥體、事件、信號量、……);
- 字段的值可以在反序列化時很簡單的重新計算出來。
字段加上[NonSerialized]屬性標簽可以阻止該字段被序列化; 如果希望字段在反序列化時被重新計算,可以定義一個方法[OnDeserialized]private void OnDeserialized(StreamingContext context){...}; 跟[OnDeserialized]相似的幾個屬性[OnSerializing] -> [OnSerialized] -> [OnDeserializing] -> [OnDeserialized]; 如果你序列化一個類型的實例,在類型中加入新的字段,然后在嘗試反序列化時,Formatter會拋出SerializationException指出成員數目不對,可以通過使用[OptionalField]屬性標簽來解決該問題。 How Formatters Serialize Type Instances
FormatterServices.GetSerializableMembers(), .GetObjectData(), GetTypeFromAssembly(), GetUninitializedObject(), .PopulateObjectMembers()靜態方法。 Controlling the Serialized/Deserialized Data
如何完全的控制序列化/反序列化,可以實現System.Runtime.Serialization.ISerializable接口; 一旦類型繼承了ISerializable接口,那么子類型也就必須實現該接口; 建議在GetObjectData方法和特殊構造器上附加[SecurityPermissionAttribute(SecurityAction.Demand, SerializationFormatter = true)]屬性標簽; 當Formatter在序列化對象圖時,先查找每一個對象,如果有一個類型實現了ISerializable接口,Formatter就忽略其他所有的客戶屬性,并構造一個新的System.Runtime.Serialization.SerializationInfo對象; 總是調用SerializationInfo.AddValue來加入序列化信息到類型中,如果字段的類型實現了ISerializable接口,別在字段上調用GetObjectData,而是調用AddValue; 如果類型是sealed,那么強烈建議將特殊構造聲明為private; 如果基類沒有實現ISerializable接口,怎樣為類型實現該接口?FormatterServices.GetSerializableMembers()。 Streaming Contexts
StreamingContext.State, .Context; StreamingContextStates {CrossProcess, CrossMachines, File, Persistence, Remoting, Other, Clone, CrossAppDomain, All}; Serializing a Type as a Different Type and Deserializing an Object as a Different Object
Serialization Surrogates
System.Runtime.Serialization.ISerializationSurrogate.GetObjectData(), .SetObjectData(); BinaryFormatter有一個bug阻止從序列化對象到其他的引用。要解決該問題,需要傳一個ISerializationSurrogate對象的引用到FormatterServices.GetSurrogateForCyclicalReference()方法; SurrogateSelector.AddSurrogate(),多個SurrogateSelector對象可以被鏈接起來,SurrogateSelector實現了ISurrogateSelector接口。 Overriding the Assembly and/or Type When Deserializing an Object
System.Runtime.Serialization.SerializationBinder使得反序列化對象到不同的類型非常容易。要做到這點,需要定義的類型繼承自抽象類SerializationBinder。 本章小結
?? 本章講了序列化和反序列化的知識,序列化可以講對象轉換成流進行傳輸或者持久化,在需要的時候通過反序列化在將對象構造出來。首先講了如何讓類型具備序列化的能力,以及如何控制序列化的過程。然后講了Formatter如何序列化類型實例,如何控制序列化/反序列化的數據,介紹了StreamingContext對象,演示了如何將對象反序列化到不同的類型實例。接著介紹了序列化代理,最后講了SerializationBinder抽象類可以用來反序列化對象到不同的類型。
轉載于:https://www.cnblogs.com/bengxia/archive/2010/05/31/1748259.html
總結
以上是生活随笔為你收集整理的CLR Via C# 3rd 阅读摘要 -- Chapter 24 – Runtime Serialization的全部內容,希望文章能夠幫你解決所遇到的問題。
如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。