閱讀460 返回首頁    go 阿裏雲 go 技術社區[雲棲]


一個關於反序列化的小問題

大家都知道,我們具有三種定義可序列化類型的方式:在類型上應用SerializableAttribute特性;應用DataContractAttribute/DataMemberAttribute特性和實現ISerializable接口。當你通過繼承一個現有的類來定義你需要被序列化的類,如果這個父類實現了ISerializable接口,如果定義不當,就會出現反序列化的問題。而且這個我們可能經常都不注意。

首先,我想自定義一個字典類型MyDictionary,其Key和Value的類型分別為String和Object。最簡單的方式莫過於直接繼承Dictionary<string, object>。為了讓MyDictionary對象可序列化,我們在類型上麵應用了SerializableAttribute特性。MyDictionary定義如下:

   1: [Serializable]
   2: public class MyDictionary : Dictionary<string, object>
   3: {    
   4: }

然後我通過下麵的代碼對MyDictionary對象進行序列化和反序列化,我直接采用的序列化器為BinaryFormatter。

   1: static void Main(string[] args)
   2: {
   3:     var dictionary = new MyDictionary();
   4:     dictionary.Add("001", "Foo");
   5:     dictionary.Add("002", "Bar");
   6:     dictionary.Add("003", "Baz");
   7:  
   8:     using (MemoryStream stream = new MemoryStream())
   9:     {
  10:         var formatter = new BinaryFormatter();
  11:         formatter.Serialize(stream, dictionary);
  12:         stream.Seek(0, 0);
  13:         dictionary = (MyDictionary)formatter.Deserialize(stream);
  14:     }
  15:  
  16:     foreach (var item in dictionary)
  17:     {
  18:         Console.WriteLine("{0}: {1}", item.Key, item.Value);
  19:     }            
  20: }

現在我們運行這段代碼,在進行但序列化的時候出現如下SerialiationException的異常,錯誤消息提示找不到構造函數。

image

通過上麵的截圖,我們可以看到具體的錯誤消息:“”,對於這個消息,我們第一個反應是在反序列化的時候找不到默認(無參)的構造函數。但是再看MyDictionary的定義,我們不曾定義任何構造函數,意味著它具有一個默認(無參)構造函數。

實際上,這裏並不是找不到默認(無參)構造函數,而是找不到一個具有特殊參數列表的構造函數。該構造函數接收兩個參數,類型分別是:SerializationInfo和StreamingContext。所以我們的解決方案很簡單,就是加上這麼一個構造函數。為此我們從新定義MyDictionary。

   1: [Serializable]
   2: public class MyDictionary : Dictionary<string, object>
   3: {
   4:     public MyDictionary() { }
   5:     protected MyDictionary(SerializationInfo info, StreamingContext context) : base(info, context) { }
   6: }

從新運行我們的程序,你就會得到想要的輸出結果:

   1: 001: Foo
   2: 002: Bar
   3: 003: Baz

如果一個類型實現了ISerializable接口(Dictionary<TKey, TValue>就實現了這個接口),你就應該定義如上一個構造函數。這算是一個約定,但是當你繼承某個類型的時候,你往往會忘記這個約定。


作者:蔣金楠
微信公眾賬號:大內老A
微博:www.weibo.com/artech
如果你想及時得到個人撰寫文章以及著作的消息推送,或者想看看個人推薦的技術資料,可以掃描左邊二維碼(或者長按識別二維碼)關注個人公眾號(原來公眾帳號蔣金楠的自媒體將會停用)。
本文版權歸作者和博客園共有,歡迎轉載,但未經作者同意必須保留此段聲明,且在文章頁麵明顯位置給出原文連接,否則保留追究法律責任的權利。
原文鏈接

最後更新:2017-10-27 11:04:18

  上一篇:go  從Trace和Debug來看條件編譯(Conditional Compilation)
  下一篇:go  為自定義配置的編輯提供”智能感知”的支持