编写高质量代码改善C#程序的157个建议——建议57:实现ISerializable的子类型应负责父类的序列化
建议57:实现ISerializable的子类型应负责父类的序列化
我们将要实现的继承自ISerializable的类型Employee有一个父类Person,假设Person没有实现序列化,而现在子类Employee却需要满足序列化的场景。不过序列化器并没有默认处理Person类型对象,这些事情只能由我们自己做。
以下是一个不妥的实现,序列化器只发现和处理了Employee中Salary字段:
- class Program
- {
- static void Main()
- {
- Employee liming = new Employee() { Name = "liming", Salary = };
- BinarySerializer.SerializeToFile(liming, @"c:\", "person.txt");
- Employee limingCopy = BinarySerializer.DeserializeFromFile<Employee>(@"c:\person.txt");
- Console.WriteLine(string.Format("姓名:{0}", limingCopy.Name));
- Console.WriteLine(string.Format("薪水:{0}", limingCopy.Salary));
- }
- }
- public class Person
- {
- public string Name { get; set; }
- }
- [Serializable]
- public class Employee : Person, ISerializable
- {
- public int Salary { get; set; }
- public Employee()
- {
- }
- protected Employee(SerializationInfo info, StreamingContext context)
- {
- Salary = info.GetInt32("Salary");
- }
- public override void GetObjectData(SerializationInfo info, StreamingContext context)
- {
- info.AddValue("Salary", Salary);
- }
- }
序列化工具类:
- public class BinarySerializer
- {
- //将类型序列化为字符串
- public static string Serialize<T>(T t)
- {
- using (MemoryStream stream = new MemoryStream())
- {
- BinaryFormatter formatter = new BinaryFormatter();
- formatter.Serialize(stream, t);
- return System.Text.Encoding.UTF8.GetString(stream.ToArray());
- }
- }
- //将类型序列化为文件
- public static void SerializeToFile<T>(T t, string path, string fullName)
- {
- if (!Directory.Exists(path))
- {
- Directory.CreateDirectory(path);
- }
- string fullPath = Path.Combine(path, fullName);
- using (FileStream stream = new FileStream(fullPath, FileMode.OpenOrCreate))
- {
- BinaryFormatter formatter = new BinaryFormatter();
- formatter.Serialize(stream, t);
- stream.Flush();
- }
- }
- //将字符串反序列化为类型
- public static TResult Deserialize<TResult>(string s) where TResult : class
- {
- byte[] bs = System.Text.Encoding.UTF8.GetBytes(s);
- using (MemoryStream stream = new MemoryStream(bs))
- {
- BinaryFormatter formatter = new BinaryFormatter();
- return formatter.Deserialize(stream) as TResult;
- }
- }
- //将文件反序列化为类型
- public static TResult DeserializeFromFile<TResult>(string path) where TResult : class
- {
- using (FileStream stream = new FileStream(path, FileMode.Open))
- {
- BinaryFormatter formatter = new BinaryFormatter();
- return formatter.Deserialize(stream) as TResult;
- }
- }
- }
输出为:
姓名:
薪水:2000
看见,Name字段并没有正确处理。这需要我们修改类型Employee中受保护的构造方法GetObjectData方法,为它加入父类字段的处理:
- [Serializable]
- public class Employee : Person, ISerializable
- {
- public int Salary { get; set; }
- public Employee()
- {
- }
- protected Employee(SerializationInfo info, StreamingContext context)
- {
- Name = info.GetString("Name");
- Salary = info.GetInt32("Salary");
- }
- public void GetObjectData(SerializationInfo info, StreamingContext context)
- {
- info.AddValue("Name", Name);
- info.AddValue("Salary", Salary);
- }
- }
修改后输出:
姓名:liming
薪水:2000
上面的例子中Person类未被设置成支持序列化。现在,假设Person类已经实现了ISerializable接口,那么这个问题处理起来会相对容易,在子类Employee中,我们只需要调用父类受保护的构造方法和GetObjectData方法就可以了。如下所示:
- [Serializable]
- public class Person : ISerializable
- {
- public string Name { get; set; }
- public Person()
- {
- }
- protected Person(SerializationInfo info, StreamingContext context)
- {
- Name = info.GetString("Name");
- }
- public virtual void GetObjectData(SerializationInfo info, StreamingContext context)
- {
- info.AddValue("Name", Name);
- }
- }
- [Serializable]
- public class Employee : Person, ISerializable
- {
- public int Salary { get; set; }
- public Employee()
- {
- }
- protected Employee(SerializationInfo info, StreamingContext context)
- : base(info, context)
- {
- Salary = info.GetInt32("Salary");
- }
- public override void GetObjectData(SerializationInfo info, StreamingContext context)
- {
- base.GetObjectData(info, context);
- info.AddValue("Salary", Salary);
- }
- }
转自:《编写高质量代码改善C#程序的157个建议》陆敏技
编写高质量代码改善C#程序的157个建议——建议57:实现ISerializable的子类型应负责父类的序列化的更多相关文章
- 编写高质量代码改善C#程序的157个建议[1-3]
原文:编写高质量代码改善C#程序的157个建议[1-3] 前言 本文主要来学习记录前三个建议. 建议1.正确操作字符串 建议2.使用默认转型方法 建议3.区别对待强制转换与as和is 其中有很多需要理 ...
- 读书--编写高质量代码 改善C#程序的157个建议
最近读了陆敏技写的一本书<<编写高质量代码 改善C#程序的157个建议>>书写的很好.我还看了他的博客http://www.cnblogs.com/luminji . 前面部 ...
- 编写高质量代码改善C#程序的157个建议——建议157:从写第一个界面开始,就进行自动化测试
建议157:从写第一个界面开始,就进行自动化测试 如果说单元测试是白盒测试,那么自动化测试就是黑盒测试.黑盒测试要求捕捉界面上的控件句柄,并对其进行编码,以达到模拟人工操作的目的.具体的自动化测试请学 ...
- 编写高质量代码改善C#程序的157个建议——建议156:利用特性为应用程序提供多个版本
建议156:利用特性为应用程序提供多个版本 基于如下理由,需要为应用程序提供多个版本: 应用程序有体验版和完整功能版. 应用程序在迭代过程中需要屏蔽一些不成熟的功能. 假设我们的应用程序共有两类功能: ...
- 编写高质量代码改善C#程序的157个建议——建议155:随生产代码一起提交单元测试代码
建议155:随生产代码一起提交单元测试代码 首先提出一个问题:我们害怕修改代码吗?是否曾经无数次面对乱糟糟的代码,下决心进行重构,然后在一个月后的某个周一,却收到来自测试版的报告:新的版本,没有之前的 ...
- 编写高质量代码改善C#程序的157个建议——建议154:不要过度设计,在敏捷中体会重构的乐趣
建议154:不要过度设计,在敏捷中体会重构的乐趣 有时候,我们不得不随时更改软件的设计: 如果项目是针对某个大型机构的,不同级别的软件使用者,会提出不同的需求,或者随着关键岗位人员的更替,需求也会随个 ...
- 编写高质量代码改善C#程序的157个建议——建议153:若抛出异常,则必须要注释
建议153:若抛出异常,则必须要注释 有一种必须加注释的场景,即使异常.如果API抛出异常,则必须给出注释.调用者必须通过注释才能知道如何处理那些专有的异常.通常,即便良好的命名也不可能告诉我们方法会 ...
- 编写高质量代码改善C#程序的157个建议——建议152:最少,甚至是不要注释
建议152:最少,甚至是不要注释 以往,我们在代码中不写上几行注释,就会被认为是钟不负责任的态度.现在,这种观点正在改变.试想,如果我们所有的命名全部采用有意义的单词或词组,注释还有多少存在的价值. ...
- 编写高质量代码改善C#程序的157个建议——建议151:使用事件访问器替换公开的事件成员变量
建议151:使用事件访问器替换公开的事件成员变量 事件访问器包含两部分内容:添加访问器和删除访问器.如果涉及公开的事件字段,应该始终使用事件访问器.代码如下所示: class SampleClass ...
- 编写高质量代码改善C#程序的157个建议——建议150:使用匿名方法、Lambda表达式代替方法
建议150:使用匿名方法.Lambda表达式代替方法 方法体如果过小(如小于3行),专门为此定义一个方法就会显得过于繁琐.比如: static void SampeMethod() { List< ...
随机推荐
- Chrome 的审查元素功能有哪些奇技淫巧
学习地址: https://www.zhihu.com/question/34682699
- 新机器连接老机器遇到的ERROR
Ansible无法连接老旧机器 报错内容: [root@BI ansible]# ansible -i /etc/ansible/hosts GameServer -m ping 10.10.113. ...
- Linux环境下安装XAMPP的PHP的PDF扩展
安装pdf扩展1. wget http://pecl.php.net/get/pdflib-4.1.2.tgz2. tar zxvf pdflib-4.1.2.tgz3. cd pdflib-4.1. ...
- php中的continue用法
continue 2 表示跳出两层 continue 默认跳出一层 if (count($content_arr) > 0 ) { // 获取相应的goods数据 $goodsdata = ar ...
- CGI/MIME/servlet术语解释
CGI→一种协议, 一种标准, 一种规范 使用CGI协议, 能够让用户访问某些动态资源的时候, 触发web服务器, 让web服务器根据CGI协议能够调用外部(web服务器外部)的程序来执行处理这个动态 ...
- mysql枚举类型与集合类型
枚举类型与集合类型 字段的值只能在给定范围中选择,如单选框,多选框 enum 单选 只能在给定的范围内选一个值,如性别 sex 男male/女female set 多选 在给定的范围内可以选择一个或一 ...
- Py修行路 python基础 (十五)面向对象编程 继承 组合 接口和抽象类
一.前提回忆: 1.类是用来描述某一类的事物,类的对象就是这一类事物中的一个个体.是事物就要有属性,属性分为 1:数据属性:就是变量 2:函数属性:就是函数,在面向对象里通常称为方法 注意:类和对象均 ...
- springboot成神之——ioc容器(依赖注入)
springboot成神之--ioc容器(依赖注入) spring的ioc功能 文件目录结构 lang Chinese English GreetingService MyRepository MyC ...
- windows Server 2008各版本有何区别?
windows Server 2008有几个版本,先一一列出来把: Windows Server 2008 Standard Edition (标准版) Windows Server 2008 ...
- 如何使用Visual Studio2015进行C++项目创建
打开Visual Studio 2015,点击程序左上角的“文件”--“新建”--“项目”. 在弹出窗口选择模板“visual C++”,在新建项目栏里选择“win32控制台应用程序”,直接点击确定. ...