引言

程序员在编写应用程序的时候往往要将程序的某些数据存储在内存中,然后将其写入某个文件或是将它传输到网络中的另一台计算机上以实现通讯。这个将程序数据转化成能被存储并传输的格式的过程被称为”序列化”(Serialization),而它的逆过程则可被称为”反序列化”(Deserialization)。通俗上讲,假如程序在运行的时候,内存中有一个对象,如果你想把这个对象的某些信息或者所有信息保存在本地,下次程序打开后,能够直接还原这个对象,怎么才能做到呢?

.Net框架对序列化机制具有非常好的支持,常用的为

二进制格式器(Binary Formatter) 、 XML格式器(XML Formatter)

不过在实际的应用中,二进制格式器往往应用于一般的桌面程序和网络通讯程序中,而XML格式器禀承了XML技术的优点,大多数被应用于.Net Remoting和XML Web服务等领域。下面我们来分析一下两种格式器各自的优点。

xml序列化

使用XML序列化或反序列化时,需要对XML序列化器指定需要序列化对象的类型和其关联的类型。

XML序列化只能序列化对象的公有属性,并且要求对象有一个无参的构造方法,否者无法反序列化。

[Serializable]和[NonSerialized]特性对XML序列化无效!所以使用XML序列化时不需要对对象增加[Serializable]特性。

public class Person

 {
public string Name;//姓名
public bool Sex;//性别,是否是男
public Person() { }//必须提供无参构造器,否则XmlSerializer将出错
public Person(string name, bool sex)
{
this.Name = name;
this.Sex = sex;
}
public override string ToString()
{
return "姓名:" + this.Name + "\t性别:" + (this.Sex ? "男" : "女");
}
/// <summary>
/// 对象序列化成 XML String
/// </summary>
public string XmlSerialize<T>(T obj)
{
string xmlString = string.Empty;
XmlSerializer xmlSerializer = new XmlSerializer(typeof(T));
using (MemoryStream ms = new MemoryStream())
{
xmlSerializer.Serialize(ms, obj);
xmlString = Encoding.UTF8.GetString(ms.ToArray());
}
return xmlString;
}
// <summary>
/// XML String 反序列化成对象
/// </summary>
public T XmlDeserialize<T>(string xmlString)
{
T t = default(T);
XmlSerializer xmlSerializer = new XmlSerializer(typeof(T));
//此处用的是MemoryStream
using (Stream xmlStream = new MemoryStream(Encoding.UTF8.GetBytes(xmlString)))
{
using (XmlReader xmlReader = XmlReader.Create(xmlStream))
{
Object obj = xmlSerializer.Deserialize(xmlReader);
t = (T)obj;
}
}
return t;
}

二进制序列化

使用二进制序列化,必须为每一个要序列化的的类和其关联的类加上[Serializable]特性,对类中不需要序列化的成员可以使用[NonSerialized]特性。

二进制序列化对象时,能序列化类的所有成员(包括私有的),且不需要类有无参数的构造方法

使用二进制格式序列化时,它不仅是将对象的字段数据进行持久化,也持久化每个类型的完全限定名称和定义程序集的完整名称(包括包称、版本、公钥标记、区域性),这些数据使得在进行二进制格式反序列化时亦会进行类型检查。所以反序列化时的运行环境要与序列化时的运行环境要相同,要记得添加引用,否者可能会无法反序列化成功。

 [Serializable] //特性,当为某个类加了该特性后,这个类就标记为了可序列化的了。
public class Person : Animal
{ private Car _myCar; public Car MyCar
{
get { return _myCar; }
set { _myCar = value; }
} //[NonSerialized]//当前这个字段就不会被序列化了。
private string _name; public string Name
{
get { return _name; }
set { _name = value; }
}
}
  • 二进制序列化要求:

    1.被序列化的对象的类型必须标记为可序列化的。

    2.二进制序列化会把属性对应的字段序列化到文件中,所以最好类型中不要使用自动属性(编译器会自动生成字段),而要自己写属性与字段

    3.当序列化一个对象的时候,这个对象本身以及的所有父类都必须标记为可序列化的。

    4.类型中所有属性与字段的类型必须也标记为可序列化的。接口不需要。

    5.通过[NonSerialized]把某个字段标记为不可序列化的。

            Person person = new Person();
person.Name = "张三";
person.Age = 19;
person.Email = "zhangsan@yahoo.com";
person.MyCar = new Car() { Brand = "时风" }; //二进制序列化步骤:
//1.创建二进制序列化器
BinaryFormatter bf = new BinaryFormatter();
//我们希望将对象序列化到一个文件上,所以要创建一个文件流
using (FileStream fsWrite = File.OpenWrite("person.bin"))
{
//开始执行二进制序列化
bf.Serialize(fsWrite, person);
}
Console.WriteLine("序列化完毕!");
Console.ReadKey();

反序列化的时候,需要创建原来被序列化的类型的对象,所以反序列化的时候需要引用被序列化的类型的对象。正是因为如此,所以在二进制序列化的时候,那些属性名、方法等根本不需要序列化,只需要把那些状态信息(数据→字段的值)序列化了就好了,对于那些方法等信息,在反序列化时,创建对象的时候会自动创建,然后根据序列化文件中的字段的值,进行赋值。

c#基础语言编程-序列化的更多相关文章

  1. c#基础语言编程-程序集和反射

    程序集 什么是程序集? 1.程序集(assembly)是一个及一个以上托管模块,以及一些资源文件的逻辑组合. 2.程序集是组件复用,以及实施安全策略和版本策略的最小单位. 3.程序集是包含一个或者多个 ...

  2. c#基础语言编程-正则表达式应用

    引言 在不同语言中虽正则表达式一样,但应用函数还是有所区别,在c#语言中使用Regex. 可以通过以下两种方式之一使用正则表达式引擎: 通过调用 Regex 类的静态方法. 方法参数包含输入字符串和正 ...

  3. c#基础语言编程-正则表达式基础

    引言 正则表达式是一种用高度抽象的字符串来描述字符串特征,进而实现对字符串的匹配.提取.替换等等.正则表达式(以下简称正则,Regex)通常不独立存在,各种编程语言和工具作为宿主语言提供对正则的支持, ...

  4. c#基础语言编程-文件流操作

    引言 在System.IO 命名空间下提供了一系列的类,我们可以通过相应的类进行文件.目录.数据流的操作. 1.File类:提供用于创建.复制.删除.移动和打开文件的静态方法.File类 2.File ...

  5. c#基础语言编程-编码

    字符编码是计算机技术的基础理论,其字符编码有ASCII码.UTF-8.还有就是GB2312,当然这是在中国常用的. 1.ASCII码 在计算机内部所有的信息都是以二进制字符进行存储.用每个二进制位中的 ...

  6. c#基础语言编程-Path和Directory

    引言 在程序常会对文件操作,在对文件操作中需要对文件路径的进行定位,在.Net中针对寻找文件提供两个静态类以供调用,Path和Directory. Path类 来自命名空间SYstem.IO,Path ...

  7. c#基础语言编程-装箱和拆箱

    引言 为什么有装箱和拆箱,两者起到什么作用?NET的所有类型都是由基类System.Object继承过来的,包括最常用的基础类型:int, byte, short,bool等等,就是说所有的事物都是对 ...

  8. c#基础语言编程-多态

    语言中的多态性是为了使程序有扩展性,为实现多态性,在程序中体现为接口.抽象类.父类.具体类. 接口就是一种规范,解决了多重继承的问题,类似一种规范,告诉我要做什么,具有什么能力,在接口中定义写行为属性 ...

  9. c#基础语言编程-集合

    引言 在c#常用的集合分为非泛型集合和泛型集合. 非泛型集合的类和接口位于System.Collections命名空间.这些接口和类定义各种对象(如列表.队列.位数组.哈希表和字典)的集合. 泛型集合 ...

随机推荐

  1. jquery自动切换tabs选项卡

    <%@ page language="java" contentType="text/html; charset=utf-8"    pageEncodi ...

  2. C#中Socket用法,多个聊天和单一聊天。

    自己琢磨Socket刚刚几天,所以整理出来和大家共享一下.废话少说直接进入正题. 在C#中提供了两种网络服务,一种是Socket类,另一种是TcpListener(服务器),TcpClient(客户端 ...

  3. bitVector@ java bit自我practice##Q&A:为何int 来初始化size of bitVector?long,甚至是BigInteger等策略

    /* * BitSets are packed into arrays of "words." Currently a word is * a long, which consis ...

  4. ASP.NET MVC 中使用JavaScriptResult

    在浏览器地址栏输入地址,在页面上想通过脚本弹出一个框,看到Controller下有个JavaScript方法,返回的类型是JavaScriptResult,于是想用这个方法弹出框, public Ac ...

  5. 安装linux系统后要做的事情

    基本安装0 http://www.kali.org.cn/thread-20517-1-1.html 基本安装1 http://defcon.cn/1618.html 基本安装2 http://www ...

  6. 【产品体验】echo回声

    本人产品新人,学习中,希望大家用过该产品的给点意见,不吝赐教哦~~ 先来两张echo的界面图镇楼——        echo简介: “echo”是一款做声音社交的APP,在这里,你可以感受到声音无限的 ...

  7. 在线CSS圆角生成器

    http://www.paibaidu.com/demo/CSSBorder/CSSBorder.html

  8. Linux iconv使用

    iconv [选项]文件 输入/输出格式规范:-f, --from-code=名称 原始文本编码-t, --to-code=名称 输出编码 信息:-l, --list 列举所有已知的字符集 输出控制: ...

  9. 14.8.3 Physical Row Structure of InnoDB Tables InnoDB 表的物理行结构

    14.8.3 Physical Row Structure of InnoDB Tables InnoDB 表的物理行结构 一个InnoDB 表的物理行结构取决于在创建表指定的行格式 默认, Inno ...

  10. Linux Eclipse代码提示功能设置(Java & C/C++)

    最近在Linux下开发,由于长期使用Visual Studio 2010,对代码提示功能情有独钟,现在在Linux下,使用Eclipse做开发,当然免不了怀念Visual Studio强悍的代码提示, ...