一个关于反序列化的小问题

大家都知道,我们具有三种定义可序列化类型的方式:在类型上应用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的异常,错误消息提示找不到构造函数。

二、解决问题

通过上面的截图,我们可以看到具体的错误消息:“The constructor to deserialize an object of type 'DeserializationIssue.MyDictionary' was not found.”,对于这个消息,我们第一个反应是在反序列化的时候找不到默认(无参)的构造函数。但是再看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
如果你想及时得到个人撰写文章以及著作的消息推送,或者想看看个人推荐的技术资料,可以扫描左边二维码(或者长按识别二维码)关注个人公众号(原来公众帐号蒋金楠的自媒体将会停用)。
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。

原文链接

时间: 2024-10-20 06:57:24

一个关于反序列化的小问题的相关文章

c++-一个关于递归的小程序,理解不了其输出结果。。。。。

问题描述 一个关于递归的小程序,理解不了其输出结果..... 一个c++递归的小程序,其输出结果理解不了,请问这个递归的基例是"cout<<endl;"这个吗? void f(char ch){ if (('A' <= ch) && (ch <= 'H')){ f(ch - 1); cout << ch; } else cout << endl; } int main(){ f('C'); } 输出结果为: (空一行) A

HTML5实现一个能够移动的小坦克示例代码

HTML5一词想必大家早已如雷贯耳,其功能很强大,本文为大家介绍下通过其实现一个能够移动的小坦克,具体如下,喜欢HTML的朋友可以参考下     复制代码 代码如下: <!DOCTYPE html> <html> <head> </head> <body onkeydown="changeDirect()"> <canvas id="tankMap" width="500px" h

SQL数据库上面显示一个绿色向上的小箭头是怎么回事?也无法访问数据库了,有什么办法吗?

问题描述 SQL数据库上面显示一个绿色向上的小箭头是怎么回事?也无法访问数据库了,有什么办法吗? 解决方案 sql 有一个browser服务 这个是1434端口的 解决方案二: 你那里是sqlserver客户端吗 你看看sqlservernetmanager里的网络配置1433开了吗 解决方案三: 数据库服务是否启动,端口是否在侦听,防火墙是否拦截请求

mfc-C++6.0一个关于static的小问题

问题描述 C++6.0一个关于static的小问题 static可以通过拖动来滚动上面的绘图么?重新绘图的定位是怎么样的,MFC 解决方案 scrollviewhttp://blog.csdn.net/scyatcs/article/details/7942585 解决方案二: 可以,但是需要给static手动的绑定一个滚动条才可以,重绘的本质就刷新界面的同时,改变绘图的点坐标,定位的话可以根据滚动条当前位置对绘图的坐标进行一个计算和显示 解决方案三: 省事儿点的方式是直接在单文档程序中绘图,这

一个JavaScript的求爱小特效_javascript技巧

这里面做了一个JavaScript的求爱小特效,效果如下: 不仅能出现下面的图的效果,还可以让这个图形跟随着鼠标转动哦,这里面只是一个简单的没有修饰的小例子,基于这个例子可以让求爱,更加好玩了.闷骚男们,是不是可以给你的小萝莉发个这样的网页啊.给力的. 贴上code吧: 复制代码 代码如下: <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>Insert t

mysql-求大神帮忙调试一个Struts+MySQL的小项目

问题描述 求大神帮忙调试一个Struts+MySQL的小项目 该软件要求采用Struts2+MYSQL方式实现,能够快速查询车源信息. 能够准确填写发货单. 能够实现实现发货单查询. 能够实现对回单处理. 能够对车源信息进行添加,修改和删除. 能够对客户信息进行管理. 项目是我照着资料书上敲的,每次运行都显示连不上数据库,哪位大神愿意腾出时间的,我就把项目还有数据库的sql脚本发给您,自己是个新手,求大神们多多指教了. 解决方案 你看看数据库的驱动引入了吗,然后看看用户名和密码是不是打错了,把连

android-如何在每一个EditText中放入小的行线?

问题描述 如何在每一个EditText中放入小的行线? 我想在 Edit Texts 里添加小的行,照下面的样子,如何实现? 解决方案 看看你要找的是不是这个http://blog.csdn.net/yhm2046/article/details/9183673 解决方案二: 就是替换下backGround的selector就好了

for-请教各位 一个简单的 java 小问题

问题描述 请教各位 一个简单的 java 小问题 int arr[]={1,2,3,4,5,6,7,8,9,10}; int i,temp; for(i=0;i<10;i++){ } System.out.println("a"+i); temp=arr[0]; for(i=0;i<9;i++){ arr[i]=arr[i+1]; } System.out.println("b"+i); System.out.println("c"+

有一个关于Java的小题目,做了好久做不出来,还请大神帮我!

问题描述 有一个关于Java的小题目,做了好久做不出来,还请大神帮我! 请大家帮帮我,明天就要交作业了!5555555 解决方案 哪里做不出来,,,说下 解决方案二: 这是小题目么我想问....85分 解决方案三: 这都是一个功能了好不?关键你这也没说你哪儿不会啊 解决方案四: 页面不会写还是后台不会?你总得说清楚啊 解决方案五: 如果你搭好了框架,还是来张项目目录结构图来看看先