C#—序列化(Serialize)和反序列化(NonSerialize)
(转自:http://www.cnblogs.com/Abel-Zhang/p/Serialize.html)
一、概述
序列化是把对象转变成流。相反的过程就是反序列化。
哪些场合用到这项技术呢?
1. 把对象保存到本地,下次运行程序时恢复这个对象。
2. 把对象传送到网络的另一台终端上,然后在此终端还原这个对象。
3. 复制系统的粘帖板中,然后用快捷键Ctrl+V恢复这个对象。
常用的序列化流有Binary(二进制流),XML,SOAP。
二、序列化和反序列化使用事例:
这里我们把序列化和反序列化以功能类的形式展现:

public class Serializer
{
//将类型序列化为字符串
public static string Serialize<T>(T t) where T : class
{
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) where T : class
{
if (!Directory.Exists(path))
{
Directory.CreateDirectory(path);
}
string fullPath = string.Format(@"{0}\{1}", path, fullName);
using (FileStream stream = new FileStream(fullPath,FileMode.OpenOrCreate))
{
BinaryFormatter formatter = new BinaryFormatter();
formatter.Serialize(stream, t);
stream.Flush();
}
} //将类型序列化为文件
public static void SerializeToFileByXml<T>(T t, string path, string fullName) where T : class
{
if (!Directory.Exists(path))
{
Directory.CreateDirectory(path);
} string fullPath = string.Format(@"{0}\{1}", path, fullName); using (FileStream stream = new FileStream(fullPath, FileMode.OpenOrCreate))
{
XmlSerializer formatter = new XmlSerializer(typeof(T));
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;
}
} //将xml文件反序列化为类型
public static TResult DeserializeFromFileByXml<TResult>(string path) where TResult : class
{
using (FileStream stream = new FileStream(path, FileMode.Open))
{
XmlSerializer formatter = new XmlSerializer(typeof(TResult)); ;
return formatter.Deserialize(stream) as TResult;
}
}
}

上面事例中的方法是以泛型方法实现的,其中附加了泛型约束,保证泛型安全。
序列化功能类有了下面我们建一个Book对象,用它来测试我们的功能类。

[Serializable]
public class Book
{
[NonSerialized]
private string _bookPwd;
[field: NonSerialized]
public event EventHandler NameChanged;
private string _bookName;
private string _bookID;
public ArrayList alBookReader;
public string _bookPrice; public Book()
{
alBookReader = new ArrayList();
} public string BookName
{
get { return _bookName; }
set
{
if (NameChanged != null)
{
NameChanged(this, null);
}
_bookName = value;
}
} public void BookPwd(string pwd)
{
_bookPwd=pwd;
} public string BookID
{
get { return _bookID; }
set { _bookID = value; }
} public void SetBookPrice(string price)
{
_bookPrice = price;
} [OnDeserializedAttribute]
public void changeName(StreamingContext context)
{
this.BookName = "C#深入浅出";
} public void Write()
{
Console.WriteLine("Book ID:" + BookID);
Console.WriteLine("Book Name:" + BookName);
Console.WriteLine("Book Password:" + _bookPwd);
Console.WriteLine("Book Price:" + _bookPrice);
Console.WriteLine("Book Reader:");
for (int i = 0; i < alBookReader.Count; i++)
{
Console.WriteLine(alBookReader[i]);
}
}
}

关键介绍:
1.[Serializable]特性定义该类型可以被序列化;
2.[NonSerialized]定义某个属性不被序列化,即:内部成员被NonSerialized禁止序列化特性标记;
3.[field: NonSerialized]定义事件不被序列化;
4.[OnDeserializedAttribute]当它应用于某个方法时,会指定对象被反序列化后立即执行此方法。
5.[OnDeserializingAttribute]当它应用于某个方法时,会指定对象被反序列化时立即执行此方法。
6.[OnSerializedAttribute]如果将对象图应用于某个方法时,会指定在序列化该对象图后是否调用此方法。
7.[OnSerializingAttribute]当它应用于某个方法时,会指定在对象序列化前调用此方法。、
我们用控制台程序实现序列化和反序列化:

static void Main(string[] args)
{
string path = "c:\\Test\\";
Book book = new Book();
book.NameChanged += new EventHandler(make_NameChanged);
book.BookID = "2001";
book.alBookReader.Add("Abel");
book.alBookReader.Add("Tomson");
book.BookName = "敏捷无敌";
book.BookPwd("*****");
book.SetBookPrice("102.00");
//对象序列化
Serializer.SerializeToFileByXml<Book>(book, path, "book.txt");
//对象反序列化
Book anothorbookserialize = new Book();
anothorbookserialize = Serializer.DeserializeFromFileByXml<Book>(path + "book.txt");
anothorbookserialize.Write();
Console.ReadKey();
} static void make_NameChanged(object sender, EventArgs e)
{
Console.WriteLine("Name Changed");
}

我们的事例是调用XML序列化流文件形式,序列化执行后的文件如下:

<?xml version="1.0"?>
<Book xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<alBookReader>
<anyType xsi:type="xsd:string">Abel</anyType>
<anyType xsi:type="xsd:string">Tomson</anyType>
</alBookReader>
<_bookPrice>102.00</_bookPrice>
<BookName>敏捷无敌</BookName>
<BookID>2001</BookID>
</Book>

反序列化输出如下:
Name Changed
Book ID:2001
Book Name:敏捷无敌
Book Password:
Book Price:102.00
Book Reader:
Abel
Tomson
结果分析:
[NonSerialized]Book Password属性在序列化XML文件中没有出现Book Password。
[field: NonSerialized]NameChanged事件,在序列化XML文件中没有出现NameChanged。
[OnDeserializedAttribute]changeName()方法,执行反序列化后没有立即执行changeName()方法,Book Name名称没有改变,需要通过Binary流形式才能成功执行方法。
//序列化
Serializer.SerializeToFile<Book>(book, path, "book.txt");
//反序列化
anothorbookserialize = Serializer.DeserializeFromFile<Book>(path + "book.txt");
我们以XML流为例是为了更好的理解序列化和反序列化的执行过程,实际应用中多数以Binary流形式实现序列化和反序列化较多。
三、继承ISerializable接口更灵活的控制序列化过程:
当以上Serializable特性无法满足复杂的序列化过程时就需要实现ISerializable接口了。
以下是格式化器的工作流程:如果格式化器在序列化一个对象的时候,发现对象实现了ISerializable接口,那他会忽略类所有序列化特性,转而调用GetObjectData方法的一个SerializationInfo对象,方法内部负责该对象属性的添加。反序列化时调用该对象受保护带参数构造方法中的一个SerializationInfo对象,方法内部对象属性赋值。
下面我们实现ISerializable接口的子类型应负责父类型的序列化为例:
1.父类同样实现了ISerializable接口

[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)
{
Salary = info.GetInt32("Salary");
Name = info.GetString("Name");
} public override void GetObjectData(SerializationInfo info, StreamingContext context)
{
base.GetObjectData(info,context);
info.AddValue("Salary", Salary);
}
}

注意:Employee中的GetObjectData方法覆盖了基类Person中的虚方法GetObjectData。
Employee employee = new Employee() { Name = "Abel", Salary=1220 };
BinarySerializer.SerializeToFile<Employee>(employee, strFile, "employee.txt");
employee = BinarySerializer.DeserializeFromFile<Employee>("c:\\Test\\employee.txt");
Console.WriteLine(employee.Name);
Console.WriteLine(employee.Salary);
2.若父类没有实现了ISerializable接口如何处理呢?
我们要实现继承ISerializable接口的Employee类的一个父类Person,Person没有实现ISerializable接口,序列化器没有默认去处理Person对象,只能由我们自己去做。
下面我们用具体实例实现:

[Serializable]
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");
Name = info.GetString("Name");
} public void GetObjectData(SerializationInfo info, StreamingContext context)
{
info.AddValue("Name", Name);
info.AddValue("Salary", Salary);
}
}

在这此序列化学习中我们用到了事件、泛型和流文件的处理知识,通过序列化我们可以实现本地加载,远程还原对象。
得到了一个Serializer工具类,该工具类封装了序列化和反序列化的过程。
此外,PageViewBase.JsonDeserializer<Dictionary<string, object>>(str); 可以处理json字串。
C#—序列化(Serialize)和反序列化(NonSerialize)的更多相关文章
- 序列化serialize()与反序列化unserialize()的实例
		在写序列化serialize与反序列化unserialize()时,我们先来看看: serialize - 产生一个可存储的值的表示 描述 string serialize ( mixed $valu ... 
- 【PHP基础】序列化serialize()与反序列化unserialize()
		序列化serialize()与反序列化unserialize(): 序列化serialize():就是将一个变量所代表的 “内存数据”转换为“字符串”的形式,并持久保存在硬盘(写入文件中保存)上的一种 ... 
- 文件读取的时候要留意 -- 序列化serialize()与反序列化unserialize():
		原文:https://blog.csdn.net/little_rabbit_baby/article/details/53840543 序列化serialize()与反序列化unserialize( ... 
- 【MFC】序列化(Serialize)、反序列化(Deserialize)
		1.首先在头文件里面声明 DECLARE_SERIAL(CSelectionSerial) 2.重写CObject的Serialize函数 virtual void Serialize(CArchiv ... 
- 【转】【C#】序列化(Serialize)、反序列化(Deserialize)
		序列化又称串行化,是.NET运行时环境用来支持用户定义类型的流化的机制.其目的是以某种存储形成使自定义对象持久化,或者将这种对象从一个地方传输到另一个地方. .NET框架提供了两种串行化的方式: 1. ... 
- 序列化serialize与反序列化unserialize
		有利于存储和传递value(除了resource类型外),却不会丢失其原有类型和结构. serialize序列化时会调用魔术方法__sleep(); unserialize反序列化时会调用魔术方法__ ... 
- 深入C#学习系列一:序列化(Serialize)、反序列化(Deserialize)
		序列化概述: 序列化 (Serialization)将对象的状态信息转换为可以存储或传输的形式的过程.在序列化期间,对象将其当前状态写入到临时或持久性存储区.以后,可以通过从存储区中读取或反序列化对象 ... 
- PHP序列化serialize()和反序列化unserialize()
		所谓的序列化,就是把保存在内存中的各种对象状态或属性保存起来,在需要时可以还原出来. serialize() 可处理除了 resource 之外的任何类型返回字符串,此字符串包含了表示 value 的 ... 
- 深入C#学习系列一:序列化(Serialize)、反序列化(Deserialize)(转)
		序列化又称串行化,是.NET运行时环境用来支持用户定义类型的流化的机制.其目的是以某种存储形成使自定义对象持久化,或者将这种对象从一个地方传输到另一个地方. .NET框架提供了两种串行化的方式: ... 
随机推荐
- 我的Android进阶之旅------>Android通用流行框架大全
			Android通用流行框架大全 缓存 图片加载 图片处理 网络请求 网络解析 数据库 依赖注入 图表 后台处理 事件总线 响应式编程 Log框架 测试框架 调试框架 性能优化 本文转载于lavor的博 ... 
- cmd命令行和bat批处理操作windows服务(转载)
			一.cmd命令行---进行Windows服务操作 1.安装服务 sc create 服务名 binPath= "C:\Users\Administrator\Desktop\win32srv ... 
- [笔记]使用Go语言Redigo包在Docker容器内连接Redis容器的方法
			Docker容器之间的连接可以带来不少方便,下面记录下如何在自己容器内通过环境变量连接与之连接的Redis容器的方法. 先起一个Redis的Docker容器,命名为 redis,再起一个自己的Dock ... 
- Java程序设计基础
			Java程序设计基础 
- python selenium firefox使用
			演示的版本信息如下: Python 3.6.0 Selenium 3.5.0 Firefox 55.0.3 geckodriver v1.0.18.0 win64 1.前提准备 1.1 安装pyth ... 
- 使用 getopt 处理命令行长参数
			getopt命令并不是bash的内建命令,它是由util-linux包提供的外部命令. getopt 与 getopts 的区别 getopts 是 shell 内建命令, getopt 是一个独立外 ... 
- NEVER QUIT. NEVER SAY NEVER.
			有志者不是从不失败,而是从不妥协. NEVER QUIT. NEVER SAY NEVER. 2015/09/15 Winners are not those who never fail but t ... 
- Linux下针对路由功能配置iptables的方法详解
			作为公司上网的路由器需要实现的功能有nat地址转换.dhcp.dns缓存.流量控制.应用程序控制,nat地址转换通过iptables可以直 接实现,dhcp服务需要安装dhcpd,dns缓存功能需要使 ... 
- 无网络环境用pip安装python类包
			1.现在有网络的电脑安装相应的包 pip install django 2.安装完成后 打包 1)新建一个文件夹(package),用来存放包: 2)执行 pip list #查看安装的包 pip f ... 
- 防盗链&CSRF&API接口幂等性设计
			防盗链技术 CSRF(模拟请求) 分析防止伪造Token请求攻击 互联网API接口幂等性设计 忘记密码漏洞分析 1.Http请求防盗链 什么是防盗链 比如A网站有一张图片,被B网站直接通过img标签属 ... 
