【转】C#中Serializable序列化实例详解
这篇文章主要介绍了C#中Serializable序列化,以实例形式详细讲述了系列化的技术及各种序列化方法,非常具有实用价值,需要的朋友可以参考下
本文实例讲述了C#中Serializable序列化。分享给大家供大家参考。具体分析如下:
概述:
序列化就是是将对象转换为容易传输的格式的过程,一般情况下转化打流文件,放入内存或者IO文件 中。例如,可以序列化一个对象,然后使用 HTTP 通过 Internet 在客户端和服务器之间传输该对象,或者和其它应用程序共享使用。反之,反序列化根据流重新构造对象。
一、几种序列化技术
1)二进制序列化保持类型保真度,这对于在应用程序的不同调用之间保留对象的状态很有用。例如,通过将对象序列化到剪贴板,可在不同的应用程序之间共享对象。您可以将对象序列化到流、磁盘、内存和网络等等。远程处理使用序列化“通过值”在计算机或应用程序域之间传递对象。
2)XML 序列化仅序列化公共属性和字段,且不保持类型保真度。当您要提供或使用数据而不限制使用该数据的应用程序时,这一点是很有用的。由于 XML 是一个开放式标准,因此,对于通过 Web 共享数据而言,这是一个很好的选择。SOAP 同样是一个开放式标准,这使它也成为一个颇具吸引力的选择。
3)使用提供的数据协定,将类型实例序列化和反序列化为 XML 流或文档(或者JSON格式)。常应用于WCF通信。
二、序列化分类
1、基本序列化
要使一个类可序列化,最简单的方法是使用 Serializable 属性对它进行标记,如下所示
复制代码代码如下:
[Serializable] public class MyObject {public int n1 = 0;public int n2 = 0;public String str = null; }
将上面的类的一个实例序列化为一个文件
复制代码代码如下:
MyObject obj = new MyObject(); obj.n1 = 1; obj.n2 = 24; obj.str = "一些字符串"; IFormatter formatter = new BinaryFormatter(); Stream stream = new FileStream("MyFile.bin", FileMode.Create, FileAccess.Write, FileShare.None); formatter.Serialize(stream, obj); stream.Close();
上面实例的反序列化
复制代码代码如下:
IFormatter formatter = new BinaryFormatter(); Stream stream = new FileStream("MyFile。bin", FileMode.Open, FileAccess.Read, FileShare.Read); MyObject obj = (MyObject) formatter.Deserialize(fromStream); stream.Close();
如果要求具有可移植性,请使用 SoapFormatter。所要做的更改只是将以上代码中的格式化程序换成 SoapFormatter,而 Serialize 和 Deserialize 调用不变。
需要注意的是,无法继承 Serializable 属性。如果从 MyObject 派生出一个新的类,则这个新的类也必须使用该属性进行标记,否则将无法序列化。例如,如果试图序列化以下类实例,将会显示一个 SerializationException,说明 MyStuff 类型未标记为可序列化。
2、选择性序列化
类通常包含不应被序列化的字段。例如,假设某个类用一个成员变量来存储线程 ID。当此类被反序列化时,序列化此类时所存储的 ID 对应的线程可能不再运行,所以对这个值进行序列化没有意义。可以通过使用 NonSerialized 属性标记成员变量来防止它们被序列化,如下所示:
复制代码代码如下:
[Serializable] public class MyObject {public int n1;[NonSerialized]public int n2;public String str; }
3、自定义序列化
可以通过在对象上实现 ISerializable 接口来自定义序列化过程。这一功能在反序列化后成员变量的值失效时尤其有用,但是需要为变量提供值以重建对象的完整状态。要实现 ISerializable,需要实现 GetObjectData 方法以及一个特殊的构造函数,在反序列化对象时要用到此构造函数。以下代码示例说明了如何在前一部分中提到的 MyObject 类上实现 ISerializable。
复制代码代码如下:
[Serializable] public class MyObject : ISerializable {public int n1;public int n2;public String str;public MyObject(){}protected MyObject(SerializationInfo info, StreamingContext context){n1 = info.GetInt32("i");n2 = info.GetInt32("j");str = info.GetString("k");}public virtual void GetObjectData(SerializationInfo info, StreamingContext context){info.AddValue("i", n1);info.AddValue("j", n2);info.AddValue("k", str);} }
在序列化过程中调用 GetObjectData 时,需要填充方法调用中提供的 SerializationInfo 对象。只需按名称/值对的形式添加将要序列化的变量。其名称可以是任何文本。只要已序列化的数据足以在反序列化过程中还原对象,便可以自由选择添加至 SerializationInfo 的成员变量。如果基对象实现了 ISerializable,则派生类应调用其基对象的 GetObjectData 方法。
需要强调的是,将 ISerializable 添加至某个类时,需要同时实现 GetObjectData 以及特殊的构造函数。如果缺少 GetObjectData,编译器将发出警告。但是,由于无法强制实现构造函数,所以,缺少构造函数时不会发出警告。如果在没有构造函数的情况下尝试反序列化某个类,将会出现异常。在消除潜在安全性和版本控制问题等方面,当前设计优于 SetObjectData 方法。例如,如果将 SetObjectData 方法定义为某个接口的一部分,则此方法必须是公共方法,这使得用户不得不编写代码来防止多次调用 SetObjectData 方法。可以想象,如果某个对象正在执行某些操作,而某个恶意应用程序却调用此对象的 SetObjectData 方法,将会引起一些潜在的麻烦。
在反序列化过程中,使用出于此目的而提供的构造函数将 SerializationInfo 传递给类。对象反序列化时,对构造函数的任何可见性约束都将被忽略,因此,可以将类标记为 public、protected、internal或 private。一个不错的办法是,在类未封装的情况下,将构造函数标记为 protect。如果类已封装,则应标记为 private。要还原对象的状态,只需使用序列化时采用的名称,从 SerializationInfo 中检索变量的值。如果基类实现了 ISerializable,则应调用基类的构造函数,以使基础对象可以还原其变量。
如果从实现了 ISerializable 的类派生出一个新的类,则只要新的类中含有任何需要序列化的变量,就必须同时实现构造函数以及 GetObjectData 方法。以下代码片段显示了如何使用上文所示的 MyObject 类来完成此操作。
复制代码代码如下:
[Serializable] public class ObjectTwo : MyObject {public int num;public ObjectTwo() : base(){}protected ObjectTwo(SerializationInfo si, StreamingContext context) : base(si,context){num = si.GetInt32("num");}public override void GetObjectData(SerializationInfo si, StreamingContext context){base.GetObjectData(si,context);si.AddValue("num", num);} }
切记要在反序列化构造函数中调用基类,否则,将永远不会调用基类上的构造函数,并且在反序列化后也无法构建完整的对象。 在反序列化过程中检索关键字/值对非常容易,但是,由于无法保证从散列表派生出的类已反序列化,所以把这些对象添加回散列表时会出现一些问题。因此,建议目前不要在散列表上调用方法。
三、如果对象的状态需要在不同版本间发生改变的方法
1、实现 ISerializable。这使您可以精确地控制序列化和反序列化过程,在反序列化过程中正确地添加和解释未来状态。
2、使用 NonSerialized 属性标记不重要的成员变量。仅当预计类在不同版本间的变化较小时,才可使用这个选项。例如,把一个新变量添加至类的较高版本后,可以将该变量标记为 NonSerialized,以确保该类与早期版本保持兼容。
希望本文所述对大家的C#程序设计有所帮助。
转载于:https://www.cnblogs.com/eedc/p/7908722.html
【转】C#中Serializable序列化实例详解相关推荐
- java中匿名内部类详解_java 中匿名内部类的实例详解
搜索热词 java 中匿名内部类的实例详解 原来的面貌: class TT extends Test{ void show() { System.out.println(s+"~~~哈哈&q ...
- java list 移除_java 中List删除实例详解
java 中List删除实例详解 1.循环删除List中的元素 public static void main(String[] args) { List t=new ArrayList(); for ...
- java 控制jsp_JSP学习之Java Web中的安全控制实例详解
普通用户界面 修改登录的Servlet,修改后的代码如下: LoginProcess.java代码: package servlet; import javabean.User; import jav ...
- java list 重复数据_java 查找list中重复数据实例详解
java 查找list中重复数据实例详解 需求: 查找一个List集合中所有重复的数据,重复的数据可能不止一堆,比如:aa, bb, aa, bb, cc , dd, aa这样的数据.如果有重复数据, ...
- file java详解_Java中File的实例详解
Java中File的实例详解 File 代表文件或者目录的类 构造函数 File(File parent,String child)---代表了指定父目录下的指定的子文件或者子目录 File(Stri ...
- java 找出重复的数据_java 查找list中重复数据实例详解
java 查找list中重复数据实例详解 需求: 查找一个list集合中所有重复的数据,重复的数据可能不止一堆,比如:aa, bb, aa, bb, cc , dd, aa这样的数据.如果有重复数据, ...
- python开发的程序中以电子表格显示数据_使用 Python 读取电子表格中的数据实例详解...
Python 是最流行.功能最强大的编程语言之一.由于它是自由开源的,因此每个人都可以使用.大多数 Fedora 系统都已安装了该语言.Python 可用于多种任务,其中包括处理逗号分隔值(CSV)数 ...
- android c++ socket编程,C++ 中 socket编程实例详解
C++ 中 socket编程实例详解 sockets(套接字)编程有三种,流式套接字(SOCK_STREAM),数据报套接字(SOCK_DGRAM),原始套接字(SOCK_RAW):基于TCP的soc ...
- python orm框架sqlalchemy_python orm 框架中sqlalchemy用法实例详解
本文实例讲述了python orm 框架中sqlalchemy用法.分享给大家供大家参考,具体如下: 一.ORM简介 1. ORM(Object-Relational Mapping,对象关系映射): ...
- jquery中cookie用法实例详解(获取,存储,删除等)
这篇文章主要介绍了jquery中cookie用法,结合实例详细分析了jQuery操作cookie的获取,存储,删除等操作,并附带了Jquery操作Cookie记录用户查询过信息实现方法,需要的朋友可以 ...
最新文章
- signature=0a26d8967069103efeee67346aac0529,Construction of Thinned Gated Single-Assignment Form
- Yii2数据缓存详解
- Flink常见流处理API
- java 经典免费教程下载
- 百度定位---适配8.0限制后台定位
- 03JavaScript程序设计修炼之道_2019-06-18_21-27-56_事件onchange
- 3个开源TTS(五)eSpeak1.06的源码调试分析
- XMind 8 Update 7 激活
- 信息收集工具之hping安装和使用
- java参数配置jconsole_jconsole 配置详解
- 软工网络15团队作业8——Beta阶段敏捷冲刺(Day4)
- 【TIC6657 DSP学习笔记】02 RTSC平台配置组件创建
- latex表格中如何画虚线
- 企业微信---第三方应用开发 笔记
- xshell卸载不干净导致无法安装
- 最新计算机安全参考文献,最新计算机络安全参考文献 计算机络安全期刊参考文献哪里找...
- 【图像语义分割】Large Kernel Maters--Improved Semantic Segmentation by Global ConvNet
- Linux-linux系统函数
- 触宝今日纽交所上市,从全球化走向融合发展!
- kafka 安装和启动