.Net组件程序设计之序列化
.Net组件程序设计之序列化
自动序列化
本篇给大家讲解一下在.NET中的序列化,它的用处非常之多,特别是对于某种环境下保存某种状态是很好的方法,接下来就来看一下吧。
Serializable属性
[Serializable]
public class SerializableCase { public SerializableCase() { } private string _State; public string State { get { return _State; } set { _State = value; } } }
在上面的示例类型上加上Serializable属性这样将示例类型标记为可序列化类型.
格式化序列化器
二进制格式器
public class MySerializableCase
{
public static void BinaryFormatterSerialize()
{
IFormatter formatter = new BinaryFormatter();
Stream stream = new FileStream("jin.glory", FileMode.Create, FileAccess.ReadWrite);
using (stream)
{
SerializableCase serCase = new SerializableCase();
serCase.State = "Test";
formatter.Serialize(stream, serCase);
}
} public static void BinaryFormatterDesSerialize()
{
Stream stream = new FileStream("jin.glory", FileMode.Open, FileAccess.Read);
IFormatter formatter = new BinaryFormatter();
using (stream)
{
SerializableCase serCase = formatter.Deserialize(stream) as SerializableCase;
return serCase.State;
}
}
}
BinaryFormattSerialize()方法里只是实例化SerializableCase类型,然后对State属性赋值,代表一个状态。调用 MySerializableCase.BinaryFormattSerialize()后.NET把序列化好的文件流保存到了jin.glory文件中.
图1

文件的名称和后缀格式都是自己随便定义的。然后再调用反序列化,获取到之前序列化的对象状态。
string state = MySerializableCase.BinaryFormattDesSerialize();
Console.WriteLine(state);
图2

SOAP格式器
SoapFormatter是在命名空间System.Runtime.Serialization.Formatters.Soap下的(在System.Runtime.Serialization.Formatters.Soap.dll中)
public class MySerializableCase
{
public static void SoapFormatterSerialize()
{
IFormatter formatter = new SoapFormatter();
Stream stream = new FileStream("Soap.xml", FileMode.Create, FileAccess.ReadWrite);
using (stream)
{
SerializableCase serCase = new SerializableCase();
serCase.State = "Test";
formatter.Serialize(stream, serCase);
}
} public static string SoapFormatterDesSerialize()
{
Stream stream = new FileStream("Soap.xml", FileMode.Open, FileAccess.Read);
IFormatter formatter = new SoapFormatter();
using (stream)
{
SerializableCase serCase = formatter.Deserialize(stream) as SerializableCase;
return serCase.State;
}
}
}
和上面的二进制格式化器使用的方式近乎相同,唯一不同的是,使用Soap格式化器生成的序列化文件耗时更长,占用空间也比较大,但是它是遵循着SOAP协议的,这在跨平台操作数据间是很有用的,平台只需要解析重建就能把对象重新的生成出来。
不可序列化成员
[Serializable]
public class SerializableCase
{
public SerializableCase() { } private string _State; public string State
{
get { return _State; }
set { _State = value; }
} [NonSerialized]
private DonotSerializable _DonotSerializable; public DonotSerializable DonotSerializable
{
get { return _DonotSerializable; }
set { _DonotSerializable = value; }
}
}
public class DonotSerializable
{
public DonotSerializable() { } public string DonotSerializableData
{
get;
set;
}
}
修改了一下第一段的示例代码,增加了个属性,并且设置其字段为NonSerialized,这样在.NET序列化这个类的实例的时候,检测到了[NonSerialized]的时候就会跳过它,因为有的对象确实是不适合序列化来进行持久化的,不过这样的做的也会有个问题,就是对象的状态丢失,就是不可序列化的部分会丢失。看一下下面的代码:
public class MySerializableCase
{
public static void BinaryFormatterSerialize()
{
IFormatter formatter = new BinaryFormatter();
Stream stream = new FileStream("jin.glory", FileMode.Create, FileAccess.ReadWrite);
using (stream)
{
SerializableCase serCase = new SerializableCase();
serCase.State = "Test";
serCase.DonotSerializable = new DonotSerializable();
serCase.DonotSerializable.DonotSerializableData = "DonotSerializableData";
formatter.Serialize(stream, serCase);
}
} public static string BinaryFormatterDesSerialize()
{
Stream stream = new FileStream("jin.glory", FileMode.Open, FileAccess.Read);
IFormatter formatter = new BinaryFormatter();
using (stream)
{
SerializableCase serCase = formatter.Deserialize(stream) as SerializableCase;
return serCase.State+"_"+serCase.DonotSerializable.DonotSerializableData;
}
}
}
修改了上面的二进制格式器的代码,调用一下测试代码我们一起来看下结果:
MySerializableCase.BinaryFormatterSerialize();
string state = MySerializableCase.BinaryFormatterDesSerialize();
Console.WriteLine(state);
图3

在反序列化的时候,对象SerializableCase的DonotSerializable属性丢失了,所以才会报错。
对于这样的情况,.NET提供了IDeserializationCallback接口,它里面只有一个函数void OnDeserialization(object sender),只要实现了IDeserializationCallback,并且在OnDeserialization函数里实现具体的对不可序列化对象的初始化。
[Serializable]
public class SerializableCase:IDeserializationCallback
{
public SerializableCase() { } private string _State; public string State
{
get { return _State; }
set { _State = value; }
} [NonSerialized]
private DonotSerializable _DonotSerializable; public DonotSerializable DonotSerializable
{
get { return _DonotSerializable; }
set { _DonotSerializable = value; }
} public void OnDeserialization(object sender)
{
_DonotSerializable = new DonotSerializable();
_DonotSerializable.DonotSerializableData = "DonotSerializableData->Test";
}
}
按照上面的调用方式,来看一下结果:
图4

这样是在反序列化的时候,如果检测到了实例类型实现了IDeserializationCallback接口,是在反序列化完成的时候会执行实现了IDeserializationCallback的OnDeserialization()方法,这样可以对一些不可序列化的属性状态在这个方法里来实现。
序列化事件
.NET2.0
引进了对序列化事件的支持,当序列化和反序列化的时候,.NET在你的类上调用指定的方法,.NET中定义了四个序列化和反序列化事件。
serializing事件是在序列化发生之前被触发,
serialized 事件是在序列化之后被触发,
deserializing事件是在反序列化之前被触发,
deserialized事件是在反序列化之后被触发。
引用先前的示例代码SerializableCase类的初始代码:
[Serializable]
public class SerializableCase //:IDeserializationCallback
{
public SerializableCase() { }
private string _State;
public string State
{
get { return _State; }
set { _State = value; }
}
}
添加了事件后的示例代码是这样的:
[Serializable]
public class SerializableCase
{
public SerializableCase() { }
private string _State;
public string State
{
get { return _State; }
set { _State = value; }
} [OnSerializing]
private void OnSerializing(StreamingContext context)
{
_State = "此时的状态是:序列化之前";
Console.WriteLine(State);
} [OnSerialized]
private void OnSerialized(StreamingContext context)
{
_State = "此时的状态是:序列化之后";
Console.WriteLine(State);
} [OnDeserializing]
private void OnDeserializing(StreamingContext context)
{
_State = "此时的状态是:反序列化之前";
Console.WriteLine(State);
} [OnDeserialized]
private void OnDeserialized(StreamingContext context)
{
_State = "此时的状态是:反序列化之后";
Console.WriteLine(State);
}
}
使用之前定义好的MySerializableCase类型中的静态方法,稍作修改来演示一下,
public static void SoapFormatterSerialize()
{
IFormatter formatter = new SoapFormatter();
Stream stream = new FileStream("Soap.xml", FileMode.Create, FileAccess.ReadWrite);
using (stream)
{
SerializableCase serCase = new SerializableCase();
formatter.Serialize(stream, serCase);
}
}
public static string SoapFormatterDesSerialize()
{
Stream stream = new FileStream("Soap.xml", FileMode.Open, FileAccess.Read);
IFormatter formatter = new SoapFormatter();
using (stream)
{
SerializableCase serCase = formatter.Deserialize(stream) as SerializableCase;
return serCase.State;
} }
测试代码:
MySerializableCase.SoapFormatterSerialize();
MySerializableCase.SoapFormatterDesSerialize();
Console.ReadLine();
图5

从结果中就很明显的显示出来了,这里要说几句题外话,细心的朋友可能发现了,在SerializableCase类型中的四个事件函数签名都是相同的,这是因为在.NET中为这个这个序列化和反序列化事件定义的委托就是这个签名,在这个类型实例序列化和反序列化的时候会检测到.NET会反射实例内部所有的函数 检测是否有附加了序列化事件,如果判断了有则会继续检查这个函数的签名,如果函数签名也匹配了,就会把这个函数挂上委托。
可以这样指定一个函数为事件指定调用函数:
[OnSerializing]
[OnSerialized]
[OnDeserializing]
[OnDeserialized]
private void OnGenericSerializEventMethod(StreamingContext context)
{
……
}
本篇幅序列化内容结束。
作者:金源
出处:http://www.cnblogs.com/jin-yuan/
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面
.Net组件程序设计之序列化的更多相关文章
- .Net组件程序设计之远程调用(一)
.Net组件程序设计之远程调用(一) 1应用程序域 我们知道我们写的C#代码是在操作系统逻辑体系结构中最上层的,然而操作系统本身是不会认识C#代码的,它只认识机器代码.那我们写的程序经过编译后是编译成 ...
- .Net组件程序设计之远程调用(二)
.Net组件程序设计之远程调用(二) 激活模式 引用封送对象激活类型两种, 一种是客户端激活类型,一种是服务器端激活. 客户端激活对象 客户端激活方式:当客户端创建一个远程对象时,客户端得到的是一个新 ...
- .NET组件程序设计之线程、并发管理(二)
.Net组件程序设计之线程.并发管理(二) 2.同步线程 手动同步 监视器 互斥 可等待事件 同步线程 所有的.NET组件都支持在多线程的环境中运行,可以被多个线程并发访问,如果没有线程同步,这样的后 ...
- .Net组件程序设计之线程、并发管理(一)
.Net组件程序设计之线程.并发管理(一) 1.线程 线程 线程的创建 线程的阻塞 线程挂起 线程睡眠 加入线程 线程中止 现在几乎所有的应用程序都是多线程的,给用户看来就是一个应用程序界面(应用程序 ...
- .Net组件程序设计之上下文
.Net组件程序设计之上下文 在后续篇幅的远程调用的文章里有说到应用程序域,那是大粒度的控制程序集的逻辑存在,那么想对对象的控制又由谁来做主呢?没错了,就是上下文.CLR把应用程序域更细化了,在应用程 ...
- .Net组件程序设计之对象生命周期
.Net组件程序设计之对象生命周期 .NET 垃圾回收 IDisposable() Using语句 .NET 垃圾回收 是CLR管理着垃圾回收器,垃圾回收器监控着托管堆,而我们使用的对象以及系统启动是 ...
- .Net组件程序设计之异步调用
.Net组件程序设计之异步调用 说到异步调用,在脑海中首先想到就是BeginInvoke(),在一些常用对象中我们也会常常见到Invoke()和BeginInvoke(), 要想让自己的组件可以被客户 ...
- .Net组件程序设计
.Net组件程序设计之上下文 在后续篇幅的远程调用的文章里有说到应用程序域,那是大粒度的控制程序集的逻辑存在,那么想对对象的控制又由谁来做主呢?没错了,就是上下文.CLR把应用程序域更细化了,在应用程 ...
- Json.Net组件指定/忽略序列化字段属性技巧知识点
我们在用Json.Net序列化组件序列化类的时候,经常有这样的一个需求:指定被序列化类中的某些字段属性是要忽略的,或者是指定字段属性序列化 比如下面这个类: public class Bar { pu ...
随机推荐
- 模板类 error LNK2019: 无法解析的外部符号
如果将类模板的声明和实现写在两个独立的文件中,在构建时会出现"error LNK2019: 无法解析的外部符号 "的错误. 解决方法有: 第一种方法,就是把类模板中成员函数的声明和 ...
- AOJ 0558 Cheese【BFS】
在H * W的地图上有N个奶酪工厂,分别生产硬度为1-N的奶酪.有一只吃货老鼠准备从老鼠洞出发吃遍每一个工厂的奶酪.老鼠有一个体力值,初始时为1,每吃一个工厂的奶酪体力值增加1(每个工厂只能吃一次), ...
- Python-类的属性
类的属性,可以称为成员变量 类的方法,可以称为成员函数 对象的创建 - 创建对象的过程称之为实例化:当一个对象被创建后,包含三个方面的特性:对象句柄.属性和方法. - 句柄用于区分不同的对象(实例 ...
- windows 物理内存获取
由于我一般使用的虚拟内存, 有时我们需要获取到物理内存中的数据(也就是内存条中的真实数据), 按理说是很简单,打开物理内存,读取就可以了.但似乎没这么简单: #include "window ...
- hdu2662
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=2662 莫名其妙写了一个题,感觉还是很有价值的记录一下. 题目大意:给两个互质的数,求用无限个它们不能组 ...
- 寒冬之下,浩瀚智能开单收银打印扫描POS为何能在批发零售门店商场 车销行业 风靡!:进销存+打印扫描POS机
是一款适用于商超.餐饮.服装鞋帽.家电专营等等具有零售行业特点的企业,供企业管理人员用于管理.监控本品牌的市场占有率.门店覆盖区域.网点分布合理性等经济地理信息的工具平台. 1,功能一:业务抄单文章来 ...
- angularJS(7)
服务:AngularJS 中,服务是一个函数或对象,可在你的 AngularJS 应用中使用.AngularJS 内建了30 多个服务. 最常用的服务:$location 服务, $http 服务 ...
- ipad上自定义view的旋转适配
ios8横屏时宽高会自动转换,但是ios7不是 CGFloat screenWidth = [UIScreen mainScreen].bounds.size.width; CGFloat scree ...
- [bzoj4722]由乃
身为10班人,就凭标题,这道题是一定要做的. 但是做了才发现有毒....所以是信念和题解和大腿支撑了我! 先"假设"自己实力过硬,推出了结论:当区间过大时,必定存在一种方案可以输出 ...
- iOS 有TabBar的VC界面push后隐藏TabBar的方法
当一个UITabbarController管理多个UINavigationController的时候, 我们要从这每一个UINavigationController中push一个ViewControl ...