.NET组件程序设计 第9章 序列化和持久化
来源:互联网 发布:nginx 跳转到指定域名 编辑:程序博客网 时间:2024/05/17 04:24
序列化和持久化:
描述对象状态以某种形式存储到文件,以及后来的恢复该对象状态。
Serializable属性:
默认,用户定义类型(类,结构)不可序列化,需要显示用[Serializable]特性修饰自定义类型。
不可序列化成员:
当一个类可序列化,.NET检查其下所有成员变量都可以序列化。当序列化时,.NET发现不可序列化成员会抛出异常。
对不可序列化的成员,应该用[NonSerialized]特性修饰,这样在序列化时会忽略跳过该成员。在反序列化时,会将不可序列化对象先初始化为默认值,再用自定义步骤将之初始化为正确值。
using System.Runtime.Serialization;using System.Runtime.Serialization.Formatters.Binary;using System.IO;[Serializable]public class MyClass : IDeserializationCallback{ //该字段将不被序列化 [NonSerialized] private int m_Number = 1; #region IDeserializationCallback 成员 //在反序列化后调用,初始未序列化字段 public virtual void OnDeserialization(object sender) { //输出:0 Console.WriteLine(m_Number); m_Number = 3; //输出:3 Console.WriteLine(m_Number); } #endregion}static void Main(string[] args){ #region 序列化 //MyClass mc = new MyClass(); //IFormatter formatter = new BinaryFormatter(); //Stream stream = new FileStream(@"D:\66_Code\Se\obj.bin", FileMode.Create, FileAccess.Write); //using (stream) //{ // formatter.Serialize(stream, mc); //} #endregion #region 反序列化 MyClass obj; IFormatter formatter = new BinaryFormatter(); Stream stream = new FileStream(@"D:\66_Code\Se\obj.bin", FileMode.Open, FileAccess.Read); using (stream) { obj = (MyClass)formatter.Deserialize(stream); } #endregion Console.Read();}
委托和序列化:
//委托成员变量应标记为不可序列化[NonSerializable]private EventHandler m_MyEvent;//对于事件,要加上field属性限定[field:NonSerializable]private event EventHandler m_MyEvent;
序列化格式器:
格式器是一个实现 IFormatter接口的对象。
1.二进制格式器(BinaryFormatter)
2.SOAP格式器(SoapFormatter)
using System.Runtime.Serialization.Formatters.Soap;#region 序列化//MyClass mc = new MyClass();//IFormatter formatter = new SoapFormatter();//Stream stream = new FileStream(@"D:\66_Code\Se\obj.xml", FileMode.Create, FileAccess.Write);//using (stream)//{// formatter.Serialize(stream, mc);//}#endregion#region 反序列化MyClass obj;IFormatter formatter = new SoapFormatter();Stream stream = new FileStream(@"D:\66_Code\Se\obj.xml", FileMode.Open, FileAccess.Read);using (stream){ obj = (MyClass)formatter.Deserialize(stream);}#endregion
XML序列化(XmlSerializer):
为了面向因特网与其他平台交换数据。.NET序列化基于组件,面向应用程序和交互对象。
using System.Xml.Serialization;#region 序列化//MyClass mc = new MyClass();//XmlSerializer xml = new XmlSerializer(typeof(MyClass));//Stream stream = new FileStream(@"D:\66_Code\Se\obj.xml", FileMode.Create, FileAccess.Write);//using (stream)//{// xml.Serialize(stream, mc);//}#endregion#region 反序列化MyClass obj;XmlSerializer xml = new XmlSerializer(typeof(MyClass));Stream stream = new FileStream(@"D:\66_Code\Se\obj.xml", FileMode.Open, FileAccess.Read);using (stream){ obj = (MyClass)xml.Deserialize(stream);}#endregion
序列化事件:
当序列化或反序列化发生时,.NET支持在类上调用自定义方法处理。
[Serializable]public class MyClass{ //序列化事件(当前类必须标记为可序列化,且只有BinaryFormatter,SoapFormatter调用序列化,反序列化才有效) //除了.NET应没有其他程序能调用序列化事件,建议设为私有 [OnSerializing] private void OnSerializing(StreamingContext context) { Console.WriteLine("在序列化开始前调用"); } [OnSerialized] private void OnSerialized(StreamingContext context) { Console.WriteLine("在序列化后调用"); } [OnDeserializing] private void OnDeserializing(StreamingContext context) { Console.WriteLine("在反序列化前调用"); } //可代替OnDeserialization()方法,初始化未序列化字段 [OnDeserialized] private void OnDeserialized(StreamingContext context) { Console.WriteLine("在反序列化后及OnDeserialization()方法后调用"); }}
克隆可序列化对象(利用类存流):
//克隆可序列化对象public static T Clone<T>(T obj){ //检查当前类型是否可序列化 if (typeof(T).IsSerializable) { IFormatter formatter = new BinaryFormatter(); //将对象,序列化到内存流中保存再反序列化,完成深层次克隆对象 Stream stream = new MemoryStream(); using (stream) { formatter.Serialize(stream, obj); stream.Seek(0, SeekOrigin.Begin); T clone = (T)formatter.Deserialize(stream); return clone; } } throw new Exception();}
序列化多个对象:
[Serializable]public class MyClass{}[Serializable]public class MyOtherClass{}class Program{ static void Main(string[] args) { MyClass mc = new MyClass(); MyOtherClass moc = new MyOtherClass(); IFormatter formatter = new BinaryFormatter(); //将不同对象使用同一流序列化的同一文件中 Stream stream = new FileStream(@"D:\66_Code\Se\All.bin", FileMode.Create, FileAccess.Write); using (stream) { formatter.Serialize(stream, mc); formatter.Serialize(stream, moc); } mc = null; moc = null; //从同一文件反序列化为不同对象(注意顺序!) stream = new FileStream(@"D:\66_Code\Se\All.bin", FileMode.Open, FileAccess.Read); using (stream) { mc = (MyClass)formatter.Deserialize(stream); moc = (MyOtherClass)formatter.Deserialize(stream); } Console.Read(); }}
自定义序列化(通过实现ISerializable接口):
//实现ISerializable接口的类必用Serializable特性修饰,否则.NET将忽略该接口[Serializable]public class MyClass<T> : ISerializable{ private string m_String = "LULU"; //此处无法保证T的类型是可序列化的 private T m_Value; #region 构造函数 //为支持相匹配自定义反序列化,必须提供一反序列化构造函数 //应将该构函始终定义为受保护,防止客户端调用 protected MyClass(SerializationInfo info, StreamingContext context) { //反序列化时,将加密后的值解密还原为正确值 m_String = info.GetString("m_String").ToUpper(); //泛型 m_Value = (T)info.GetValue("m_Value", typeof(T)); } //定义静态构造函数,实现在使用该类前,执行一次运行时检查 //可用此技巧进行其他约束性检查 static MyClass() { if(typeof(T).IsSerializable == false) { throw new SerializationException("类型不可序列化!"); } } public MyClass() { } #endregion #region ISerializable 成员 //序列化对象时,.NET会先检查是否可序列化,再检查是否实现ISerializable接口 //实现该接口,就调用GetObjectData()获取对象状态 public void GetObjectData(SerializationInfo info, StreamingContext context) { //可以按照自定义方式提供值(实现加密之类,避免暴露真实值) info.AddValue("m_String", m_String.ToLower()); //泛型 info.AddValue("m_Value", m_Value, typeof(T)); } #endregion}
序列化和类层次结构:
对一个类使用Serializable特性,只影响该类,不会导致派生类可序列化。
- .NET组件程序设计 第9章 序列化和持久化
- .NET简谈组件程序设计之(初识序列化、持久化)
- .NET组件程序设计之序列化
- .Net组件程序设计之序列化
- .NET组件程序设计 第8章 多线程和并发管理
- .NET简谈组件程序设计之(渗入序列化过程)
- .NET组件程序设计 第2章
- .NET组件程序设计 第3章
- .NET组件程序设计 第6章 事件
- 序列化和持久化
- 序列化和持久化
- .NET组件程序设计 第8章 多线程和并发管理 .NET多线程服务
- .NET组件程序设计 第8章 多线程和并发管理 同步线程_监视器
- .NET组件程序设计 第8章 多线程和并发管理 同步线程_互斥
- .NET组件程序设计 第8章 多线程和并发管理 同步线程_可等待事件
- .NET组件程序设计 第8章 多线程和并发管理 同步线程_信号
- .NET组件程序设计 第8章 多线程和并发管理 同步线程_互锁,读写锁
- .NET组件程序设计 第8章 多线程和并发管理 同步委托
- asp.net 动态加载主题
- java连接sqlserver2005得心体会
- Android高人必修 Ant 编译Android工程
- 实用电脑快捷键大全
- 两种方法教你直接将文字写到桌面上。
- .NET组件程序设计 第9章 序列化和持久化
- 蛋疼的缺少“;”的调试方法
- Android JNI 使用的数据结构JNINativeMethod详解
- GridView Tutorials 详解
- ResultSet转java对象的通用解决方案
- 手把手打造属于自己的Linux系统!
- hdu1140 War on Weather
- freopen重定向stdout之后如何恢复标准句柄stdout
- android 查看系统数据库——以短信为例