在C#中的作用

上传人:鲁** 文档编号:551633829 上传时间:2023-02-03 格式:DOCX 页数:6 大小:16.08KB
返回 下载 相关 举报
在C#中的作用_第1页
第1页 / 共6页
在C#中的作用_第2页
第2页 / 共6页
在C#中的作用_第3页
第3页 / 共6页
在C#中的作用_第4页
第4页 / 共6页
在C#中的作用_第5页
第5页 / 共6页
点击查看更多>>
资源描述

《在C#中的作用》由会员分享,可在线阅读,更多相关《在C#中的作用(6页珍藏版)》请在金锄头文库上搜索。

1、简介序列化是指将对象实例的状态存储到存储媒体的过程。在此过程中,先将对象的公共字段和私 有字段以及类的名称(包括类所在的程序集)转换为字节流,然后再把字节流写入数据流。在 随后对对象进行反序列化时,将创建出与原对象完全相同的副本。在面向对象的环境中实现序列化机制时,必须在易用性和灵活性之间进行一些权衡。只要您对此 过程有足够的控制能力,就可以使该过程在很大程度上自动进行。例如,简单的二进制序列化不 能满足需要,或者,由于特定原因需要确定类中那些字段需要序列化。以下各部分将探讨.NET 框架提供的可靠的序列化机制,并着重介绍使您可以根据需要自定义序列化过程的一些重要功 能。持久存储我们经常需要将

2、对象的字段值保存到磁盘中,并在以后检索此数据。尽管不使用序列化也能完成 这项工作,但这种方法通常很繁琐而且容易出错,并且在需要跟踪对象的层次结构时,会变得越 来越复杂。可以想象一下编写包含大量对象的大型业务应用程序的情形,程序员不得不为每一个 对象编写代码,以便将字段和属性保存至磁盘以及从磁盘还原这些字段和属性。序列化提供了轻 松实现这个目标的快捷方法。公共语言运行时(CLR)管理对象在内存中的分布,.NET框架则通过使用反射提供自动的序列 化机制。对象序列化后,类的名称、程序集以及类实例的所有数据成员均被写入存储媒体中。对 象通常用成员变量来存储对其他实例的引用。类序列化后,序列化引擎将跟踪

3、所有已序列化的引 用对象,以确保同一对象不被序列化多次。.NET框架所提供的序列化体系结构可以自动正确处 理对象图表和循环引用。对对象图表的唯一要求是,由正在进行序列化的对象所引用的所有对象 都必须标记为Serializable (请参阅基本序列化)。否则,当序列化程序试图序列化未标记的 对象时将会出现异常。当反序列化已序列化的类时,将重新创建该类,并自动还原所有数据成员的值。按值封送对象仅在创建对象的应用程序域中有效。除非对象是从MarshalByRefObject派生得到或标 记为Serializable,否则,任何将对象作为参数传递或将其作为结果返回的尝试都将失败。如 果对象标记为Ser

4、ializable,则该对象将被自动序列化,并从一个应用程序域传输至另一个应 用程序域,然后进行反序列化,从而在第二个应用程序域中产生出该对象的一个精确副本。此过 程通常称为按值封送。如果对象是从MarshalByRefObject派生得到,则从一个应用程序域传递至另一个应用程序 域的是对象引用,而不是对象本身。也可以将从MarshalByRefObject派生得到的对象标记 为Serializable。远程使用此对象时,负责进行序列化并已预先配置为Surrogateselector的 格式化程序将控制序列化过程,并用一个代理替换所有从MarshalByRefObject派生得到的 对象。如果

5、没有预先配置为SurrogateSelector,序列化体系结构将遵从下面的标准序列化规 则(请参阅序列化过程的步骤)。基本序列化要使一个类可序列化,最简单的方法是使用Serializable属性对它进行标记,如下所示:Serializablepublic class MyObject public int n1 = 0;public int n2 = 0;public Stri ng str = n ull;以下代码片段说明了如何将此类的一个实例序列化为一个文件:MyObject obj = new MyObject();obj. n1 = 1;obj.n2 = 24;obj.str =一些

6、字符串;【Formatter formatter = new Bin aryFormatter();Stream stream = new FileStream(MyFile.bi n, FileMode.Create,FileAccess.Write, FileShare.None);formatter.Serialize(stream, obj);stream.Close();本例使用二进制格式化程序进行序列化。您只需创建一个要使用的流和格式化程序的实例,然后 调用格式化程序的Serialize方法。流和要序列化的对象实例作为参数提供给此调用。类中的 所有成员变量(甚至标记为private

7、的变量)都将被序列化,但这一点在本例中未明确体现出 来。在这一点上,二进制序列化不同于只序列化公共字段的XML序列化程序。将对象还原到它以前的状态也非常容易。首先,创建格式化程序和流以进行读取,然后让格式化 程序对对象进行反序列化。以下代码片段说明了如何进行此操作。IFormatter formatter = new Bin aryFormatter();Stream stream = new FileStream(MyFile.bin, FileMode.Open,FileAccess.Read, FileShare.Read);MyObject obj = (MyObject) form

8、atter.Deserialize(fromStream); stream.Close();/下面是证明Con sole.WriteLi ne( n1: 0, obj.n1);Con sole.WriteLi ne( n2: 0, obj.n 2);Co nsole.WriteLi ne(str: 0, obj.str);上面所使用的BinaryFormatter效率很高,能生成非常紧凑的字节流。所有使用此格式化程 序序列化的对象也可使用它进行反序列化,对于序列化将在.NET平台上进行反序列化的对象, 此格式化程序无疑是一个理想工具。需要注意的是,对对象进行反序列化时并不调用构造函数。 对反序

9、列化添加这项约束,是出于性能方面的考虑。但是,这违反了对象编写者通常采用的一些 运行时约定,因此,开发人员在将对象标记为可序列化时,应确保考虑了这一特殊约定。如果要求具有可移植性,请使用SoapFormatter。所要做的更改只是将以上代码中的格式化程 序换成SoapFormatter,而Serialize和Deserialize调用不变。对于上面使用的示例,该 格式化程序将生成以下结果。vSOAP-ENV:E nvelopexmlns:xsi=http:/www.w3.org/2001/XMLSchem a-instaneexmlns:xsd = http:/www.w3.org/2001/

10、XMLSchem axmlns:SOAP- ENC=http:/schemas.xmlsoap.org/soap/encoding/xmlns:SOAP- ENV=http:/schemas.xmlsoap.org/soap/envelope/SOAP-ENV:e ncodi ngStyle=http:/ /soap/e ncodi ng/clr/1.0 http:/schemas.xmls0ap.0rg/s0ap/encoding/ xmlns:al = http:/ 124 一些字符串 需要注意的是,无法继承Serializable属性。如果从MyObject派生出一个新的类,则这个 新的

11、类也必须使用该属性进行标记,否则将无法序列化。例如,如果试图序列化以下类实例,将 会显示一个SerializationException,说明MyStuff类型未标记为可序列化。public class MyStuff : MyObjectpublic int n3;使用序列化属性非常方便,但是它存在上述的一些限制。有关何时标记类以进行序列化(因为类 编译后就无法再序列化),请参考有关说明(请参阅下面的序列化规则)。选择性序列化类通常包含不应被序列化的字段。例如,假设某个类用一个成员变量来存储线程ID。当此类被 反序列化时,序列化此类时所存储的ID对应的线程可能不再运行,所以对这个值进行序列化

12、 没有意义。可以通过使用Non Serialized属性标记成员变量来防止它们被序列化,如下所示:Serializablepublic class MyObjectpublic int nl;Non Serialized public int n2;public Stri ng str;自定义序列化可以通过在对象上实现ISerializable接口来自定义序列化过程。这一功能在反序列化后成员 变量的值失效时尤其有用,但是需要为变量提供值以重建对象的完整状态。要实现ISerializable,需要实现GetObjectData方法以及一个特殊的构造函数,在反序列化对象时 要用到此构造函数。以下代

13、码示例说明了如何在前一部分中提到的 MyObject类上实现ISerializable。Serializablepublic class MyObject : ISerializablepublic int nl;public int n2; public Stri ng str;public MyObject()protected MyObject(Serializati onlnfo info, Stream ingCon text con text)n1 = in fo.GetI nt32(i);n2 = in fo.GetI nt32(j);str = in fo.GetStr in

14、g(k);public virtual void GetObjectData(Serializati onlnfo info,Streami ngCon text con text)in fo.AddValue(i, n 1);in fo.AddValue(j, n 2);in fo.AddValue(k, str);在序列化过程中调用GetObjectData时,需要填充方法调用中提供的Serializationlnfo对 象。只需按名称/值对的形式添加将要序列化的变量。其名称可以是任何文本。只要已序列化的 数据足以在反序列化过程中还原对象,便可以自由选择添加至Serializationln

15、fo的成员变量。 如果基对象实现了 ISerializable,则派生类应调用其基对象的 GetObjectData方法。需要强调的是,将ISerializable添加至某个类时,需要同时实现 GetObjectData以及特殊 的构造函数。如果缺少GetObjectData,编译器将发出警告。但是,由于无法强制实现构造函 数,所以,缺少构造函数时不会发出警告。如果在没有构造函数的情况下尝试反序列化某个类, 将会出现异常。在消除潜在安全性和版本控制问题等方面,当前设计优于 SetObjectData方 法。例如,如果将SetObjectData方法定义为某个接口的一部分,则此方法必须是公共方法, 这使得用户不得不编写代码来防止多次调用SetObjectData方法。可以想象,如

展开阅读全文
相关资源
正为您匹配相似的精品文档
相关搜索

最新文档


当前位置:首页 > 办公文档 > 解决方案

电脑版 |金锄头文库版权所有
经营许可证:蜀ICP备13022795号 | 川公网安备 51140202000112号