序列化和反序列化

相关类:

System.SerializableAttribute特性(或称为属性),

System.Runtime.Serialization.ISerializable(自定义序列化接口)

https://msdn.microsoft.com/zh-cn/library/system.runtime.serialization.iserializable.aspx,

System.Runtime.Serialization.IserializationSurrogate(自定义序列化代理接口),

System.Runtime.Serializatin.SurrogateSelector(自定义序列化代理设置类)

1:官方备注

序列化使用

BinaryFormatter(https://msdn.microsoft.com/zh-cn/library/system.runtime.serialization.formatters.binary.binaryformatter.aspx)或

SopaFormatter(https://msdn.microsoft.com/zh-cn/library/system.runtime.serialization.formatters.soap.soapformatter.aspx),使用方法类同。

System.SerializableAttribute特性:

将SerializableAttribute特性应用于一个类型可指示该类型的实例可以序化。如果正在序列化的对象图中的任何类型未应用SerializableAttribute特性,公共语言运行时则会引发SerializableException(https://msdn.microsoft.com/zh-cn/library/system.runtime.serialization.serializationexception.aspx)。

即使该类会实现ISerializable接口来控制序列化进程,仍要应用SerializableAttribute特性。

将SerializableAttribute特性应用于类型时,序列化默认情况下所有私有和公共字段。

也可以从序列化排除字段通过应用NonSerializedAttribute(https://msdn.microsoft.com/zh-cn/library/system.nonserializedattribute.aspx)特性应用于字段。如果可序列化类型的字段包含指针、句柄或其他模型针对于特定环境的数据结构,并且不能在不同的环境中以有异议的方式重建,则最好经NonSerializableAttribute特性应用于该字段。

System.Runtime.Serialization.ISerializable接口:

任何可以序列化的类都必须用SerializableAttribute进行标记。如果某个类需要控制器序列化进程,它可以实现ISerializable接口。Formatter(https://msdn.microsoft.com/zh-cn/library/system.runtime.serialization.formatter.aspx)在序列化时调用GetObjectData,并使用表示对象所需的全部数据来填充所提供的SerializationInfo(https://msdn.microsoft.com/zh-cn/library/system.runtime.serialization.serializationinfo.aspx)。Formatter使用图形中对象的类型来创建SerializationInfo。需要自己发送代理的对象可以使用SerializationInfo上的FullTypeName和AssemblyName属性来更改所传输的信息,或直接使用方法SetType,与同时设置FullTypeName和AssemblyName等效。

在类继承的情况下,可以序列化从实现ISerializable的基类中派生的类。这种情况下,派生的类应在GetObjectData的实现内调用GetObjectData的基类实现。否则,不会序列化来自基类的数据。

ISerializable接口需要带有签字(SerializationInfo,StreamingContext)的构造函数。在反序列化时,仅在格式化程序已反序列化SerializationInfo中的数据后才调用当前构造函数。一般而言,如果该类未密封,则应保护此构造函数,序列化过程会忽略此构造方法的访问修饰符,及应当使用protected或private(类被sealed修饰时)来修饰此构造方法。

无法保证对象被反序列化的顺序。例如,如果一种类型引用尚未反序列化的类型,则会引发异常。如果创建具有这种依赖关系的类型,可以通过IDeserializationCallback(https://msdn.microsoft.com/zh-cn/library/system.runtime.serialization.ideserializationcallback.aspx)接口和OnDeserialization方法来解决该问题。

序列化接口处理像处理扩展Object的类型一样,处理扩展MarshalByRefObject(https://msdn.microsoft.com/zh-cn/library/system.marshalbyrefobject.aspx)的对象类型。这些类型都可以使用SerializableAttribute来标记,并且可以将ISerializable接口实现为其他任何对象类型。它们的对象状态将被捕获并在流中持续。

当通过System.Runtime.Remotting使用这些类型时,远程处理接口会提供一个代理项,它将取代常用的序列化,而将代理序列化为MarshalByRefObject。代理项是知道如何将特定类型的对象序列化和反序列化的帮助器。代理在大多数情况下对用户不可见,其类型将是ObjRef(https://msdn.microsoft.com/zh-cn/library/system.runtime.remoting.objref.aspx)。

作为一种常规的设计模式,类很少既使用可序列化特性来标记,又扩展MarshalByRefObject。当组合这两项特性时,开发人员应仔细考虑可能的序列化和远程处理方案。MemoryStream就是一个适用的示例。当MemoryStream的基类从MarshalByRefObject扩展时,可以捕获MemoryStream的状态并随时将其还原。因此,这样做可能是有意义的:将该流的状态序列化到数据库中,并在稍后某一时间将其还原。但是,当通过远程处理来使用时,这种类型的对象将设置代理。

有关序列化MarshalByRefObject的派生类的更多信息,请参见RemottingSurrogateSelector(https://msdn.microsoft.com/zh-cn/library/system.runtime.remoting.messaging.remotingsurrogateselector.aspx)。

关于如果实现ISerializable的更多信息,请参见自定义序列化(https://msdn.microsoft.com/zh-cn/library/ty01x675.aspx)。

System.Runtime.Serialization.ISerializationSurrogate接口:

实现序列化代理选择器,此选择器允许一个对象对另一个对象执行序列化和反序列化。

System.Runtime.Serializatin.SurrogateSelector类:

序列化代理项将为用户提供一种对象,该对象可以处理不同对象的序列化要求,并且可以再必要时转换序列化数据。该类实现接口System.Runtime.Serializatin.ISurrogateSelector。

System.Runtime.Serializatin.ISurrogateSelector接口:

实现该接口的类可用于选择代理项,以使用该代理项的序列化和反序列方法对其他类进行序列化或序列化操作。

2:简单序列化

需要使用的类有SerializableAttribute特性,和BinaryFormatter,对于不需要或不应序列化的类成员需用NonSerializableAttribute特性修饰。

代码如下:

[Serializable]

public class MyItemType{

//其他成员…

[NonSerializable]

public string IgnorField{…}

}

//序列化过程

string fileName = “[文件名]”;

MyItemType t = new MyItemType();

FileStream fs = new FileStream(fileName,FileMode.Create);

IFromatter formatter = new BinaryFormatter();

formatter.Serialize(fs, t);

fs.Close();

//反序列化过程

string fileName =  “[文件名]”;

MyItemType result = null;

FileStream fs = new FileStream(fileName, FileMode.Open);

IFormatter formatter = new BinaryFormatter();

result = formatter.Deserialize(fs);

fs.Close();

3:使用ISerializable接口实现自定义序列化

继承ISerializable接口需实现方法GetObjectData,并添加一个具有签名SerializationInfo info和StreamingContext context的构造方法以供反序列化使用,须注意的是此构造方法的访问修饰符在反序列化过程中将被忽略,因此为防止此构造方法被错误的调用应对其使用较严格的访问修饰符比如protected或private。

实现此接口的类也应当使用SerializableAttribute修饰。

代码实例:

[Serializable]

public class MyItemType:Isereializable

{

//字段….

#region 自定义序列化

private MyItemType(SerializationInfo info, StreamingContext context)

{

ThisObjectStringField = info.GetValue(“keyName”, typeof(string));

ThisObjectIntField = info.GetInt32(“keyName2”);

}

public override void GetObjectData(SerializationInfo info, StreamingContext context)

{

info.AddValue(“keyName”, ThisObjectStringField, typeof(string));

//info.AddInt32(“keyName”, ThisObjectIntField);//此行错误,info没有强类型的值添加方法

}

#endregion

}

//使用方法同于简单序列化代码实例中的使用方法

4:使用IserializationSurrogate接口实现的序列化代理项

使用IserializationSurrogate实现类可对另一个类进行序列化和反序列化。

此序列化方式使用到的类或接口还包括对代理项选择的SurrogateSelector类,Iformatter实现类(此处使用BinaryFormatter)

示例代码:

//自定义序列化代理

public class Surrogate : ISerializationSurrogate

{

public void GetObjectData(object obj, SerializationInfo info, StreamingContext context)

{

if (obj is MyItemType)

{

MyItemType temp = (MyItemType)obj;

info.AddValue("props", temp, typeof(string));

}

}

public object SetObjectData(object obj, SerializationInfo info, StreamingContext context, ISurrogateSelector selector)

{

if (obj is MyItemType)

{

MyItemType temp = (MyItemType)obj;

temp.MyProperty = (string)info.GetValue("props", typeof(string));

Console.WriteLine("SetObjectData");

return temp;

}

return null;

}

//使用方法

Surrogate surrogate = new Surrogate();

SurrogateSelector selector = new SurrogateSelector();

selector.AddSurrogate(typeof(MyItemType), new StreamingContext(StreamingContextStates.All), surrogate);

formatter.SurrogateSelector = selector;

FileStream fs = new FileStream(fileName, FileMode.Open);

formatter.Deserialize(fs);

fs.Close();

//总结时间:2015-03-17

//修改时间:2015-03-23

C#序列化与反序列化方式简单总结的更多相关文章

  1. Java:对一个对象序列化和反序列化的简单实现

    名词解释 序列化:将Java对象转化成字节的过程 反序列化:将字节转化成Java对象的过程 字节:1字节(byte)= 8bit,bit就是计算机认识的二进制 序列化的作用 Java对象是在Java虚 ...

  2. C#中的Json的序列化和反序列化

    Json是一种通用的数据格式,我们在数据交换的时候,经常会用到,下面介绍c#中的json序列化和反序列化,当然也可用在asp.net,silverlight,wpf中.我们在下面实例讲解如何进行Jso ...

  3. 第一章 JacksonUtil 序列化与反序列化属性总结

    1.json-lib与Jackson 关于json-lib与Jackson对比总结如下: 1).性能方面,Jackson的处理能力高出Json-lib10倍左右. 2).json-lib已经停止更新, ...

  4. 序列化、反序列化和transient关键字的作用

    引言 将 Java 对象序列化为二进制文件的 Java 序列化技术是 Java 系列技术中一个较为重要的技术点,在大部分情况下,开发人员只需要了解被序列化的类需要实现 Serializable 接口, ...

  5. .Net类的序列化和反序列化 - 进阶者系列 - 学习者系列文章

    今天看了下以前的一个工具的代码,其中涉及到.NET类的序列化和反序列化问题,所以就写一下. 这里说一下.NET类序列化的好处..NET类在序列化之前只是一个相对狭义的类.通过序列化,能够更好的保存该类 ...

  6. java梳理-序列化与反序列化

    一背景: 之前笔记关于rpc框架介绍中,提到为了调用远程服务,需要再确定消息结构后考虑序列化与反序列化,序列化主要是把对象转换成二进制码便于网络传输,反序列化就是相反的,主要目的是生成对象便于后续处理 ...

  7. .Net中的序列化和反序列化详解

    序列化通俗地讲就是将一个对象转换成一个字节流的过程,这样就可以轻松保存在磁盘文件或数据库中.反序列化是序列化的逆过程,就是将一个字节流转换回原来的对象的过程. 然而为什么需要序列化和反序列化这样的机制 ...

  8. 浅谈C#中的序列化与反序列化

    今天我利用这篇文章给大家讲解一下C#中的序列化与反序列化.这两个概念我们再开发中经常用到,但是我们绝大部分只用到了其中的一部分,剩下的部分很多开发人员并不清楚,甚至可以说是不知道.因此我希望通过这篇文 ...

  9. Java 中序列化与反序列化

    一. 序列化和反序列化概念 Serialization(序列化)是一种将对象以一连串的字节描述的过程:反序列化deserialization是一种将这些字节重建成一个对象的过程.将程序中的对象,放入文 ...

随机推荐

  1. EF实体框架数据操作基类(转)

    //----------------------------------------------------------------// Copyright (C) 2013 河南禄恒软件科技有限公司 ...

  2. Request.ServerVariables 获取服务器或者客户端信息

    本机ip[客户端]:request.servervariables("remote_addr") 从哪个页面转到当前页面的:Request.ServerVariables(&quo ...

  3. org.springframework.beans.MutablePropertyValues.add

    最近在项目中,通过maven引入其他包时,启动报错如下: [ERROR][2016-10-08 14:01:20.716]Context initialization failed[org.sprin ...

  4. Vue.js常用指令总结

    有时候指令太多会造成记错.记混的问题,所以本文在记忆的时候会采用穿插记忆的方式,交叉比对,不易出错. 本文主要讲了一下六个指令: v-if//v-show//v-else//v-for//v-bind ...

  5. BackgroundWorker组件的作用

    当构建一个图形化的Windows Form桌面应用程序并且需要执行在应用程序主UI线程之外的线程中长时间的任务时,BackgroundWorker类就很有用了. 要使用BackgroundWorker ...

  6. 绝不在构造和析构函数中调用 virtual 函数

    看下面的这段代码,问 print调用的是基类还是派生类的版本? 答案是 基类... 可能大家会很惊讶,print不是virtual function 吗?为什么不是调用派生类的版本呢? 首先,当定义一 ...

  7. 操作各个版本的excel的链接写法

    有很有意思的网站:https://connectionstrings.com/ace-oledb-12-0/  很详细得介绍了各种写法 这里主要提两个: string strCon = @" ...

  8. js/jquery 回调函数的定义方法

    基本写法: 带参数的回调函数 以上回调函数,直接传入function作为参数,同样,还可以传入json对象作为参数...如下. 该方法的优势是可以定义多个回调函数....类似$.ajax回调函数中的s ...

  9. SE homework2

    1. (1) Fault: for循环语句中的条件表达式i > 0,不能检查到数组的第一个元素,应该为 i >= 0 . (2) test:x=[]:y=3 Expected = -1 A ...

  10. MySQL知识树-支持的数据类型

    本篇学习笔记的主要内容: 介绍MySQL支持的各种数据类型(常用),并讲解其主要特点.   MySQL支持多种数据类型,主要包括数值类型.日期和时间类型.字符串类型. 数值类型 MySQL的数值类型包 ...