宝哥软件园

中序列化和反序列化的详细说明 Net

编辑:宝哥软件园 来源:互联网 时间:2021-11-04

序列化和反序列化被认为是每个人经常听到和使用的。然而,有些人可能不知道为什么。网上有这个东西又是怎么了。net Frameword为我们实现了这个机制。在这里,我还将简单谈谈我对序列化和反序列化的理解。

一、序列化和反序列化序列化序列化是将对象转换为字节流的过程,字节流可以很容易地存储在磁盘文件或数据库中。反序列化是序列化的反向过程,也就是将字节流转换回原始对象的过程。

但是,为什么我们需要序列化和反序列化呢?这个问题涉及到序列化和反序列化的使用,

序列化的主要用途是:

1)将应用程序的状态保存在磁盘文件或数据库中,并在应用程序下次运行时恢复该状态。例如,序列化和反转在Asp.net使用)和序列化来保存和恢复会话状态。3)一组对象可以很容易地复制到Windows窗体的剪贴板,然后粘贴回同一个或另一个应用程序。如果您通过值将对象从一个应用程序域发送到另一个应用程序域,并将它们序列化为内存中的字节流,则可以使用一些其他技术来处理数据,例如加密和压缩数据。

其次,序列化和反序列化只需使用。Net框架提供两种序列化方法:

1)、二进制序列化2)、XML和SOAP序列化,简单使用序列化和反序列化:

使用系统;使用系统。IO;使用系统。运行时。序列化。格式化程序。二进制;命名空间Serializable{ [Serializable]公共类Person { public string personName[非序列化]公共字符串personHeightprivate int PeaCe;public int PoLicy { get { return PoLicy;}设置{ ProfeSsional=value;} } public void Write() { Console。write line(' Person name : ' Person name);控制台。write line(' Person height : ' Person height);控制台。WriteLine('人物年龄: ');} } class Program { static void Main(string[]args){ Person Person=new Person();person.personName=' Jerryperson.personHeight=' 175CM人。人士=22;流流=序列化(人);//要演示,请重置流。位置=0;person=nullperson=反序列化(流);人。write();控制台。read();}私有静态memory stream Serialize(Person Person){ memory stream流=new memory stream();//构造二进制序列化格式化程序二进制格式化程序=新的二进制格式化程序();//告诉序列化程序将对象序列化为stream.serialize (stream,person);回流;}私有静态Person反序列化(Stream Stream){ binary formatter binary formatter=new binary formatter();返回(个人)二进制格式化程序。反序列化(流);}}}主要调用系统下的BinnaryFormatter类。runtime . serialization . formatters .用于序列化和反序列化的二进制命名空间。调用反序列化后的结果截图:

可以看到,除了标记为非序列化的成员之外,其他成员都可以序列化。请注意,此属性只能应用于一种类型的字段,并将由派生类型继承。

SOAP和XML的序列化和反序列化与上面类似,只是更改了格式化程序,所以这里就不一一列举了。

3.控件序列化和反序列化实现控件序列化和反序列化有两种方法:

实施系统。runtime . serialization . iserializable通过on serialization、on serializable、on serialization、on serialization、on serializable、非serializable和OptionalField等属性实现接口。第一种方法是控制序列化和反序列化代码:

使用系统;使用系统。IO;使用系统。运行时。序列化;使用系统。运行时。序列化。格式化程序。二进制;命名空间控件序列化{ [Serializable]公共类Circle { private double radius//半径【非序列化】公共双区;//区域公共圆(double inputradiu){ radius=inputradiu;面积=数学。PI *半径*半径;}[OneSerialized]private void OneSerialized(streaming context上下文){ area=Math。PI *半径*半径;} public void Write() { Console。WriteLine('半径为: '半径);控制台。WriteLine('Area为: '区域);} } class Program { static void Main(string[]args){ Circle c=new Circle(10);MemoryStream流=new memory stream();binary formatter=new binary formatter();//将对象序列化到内存流中。在这里,您可以使用从系统抽象类派生的任何类型的对象。这里,我使用内存流类型。格式化程序。序列化(流,c);小溪。位置=0;c=nullc=(圆形)格式化程序。反序列化(流);c . Write();控制台。read();}}}运行结果为:

注意:如果OnDeserialized属性被注释掉,则区域字段的值为0,因为区域字段没有序列化到流中。

在上述需要序列化的对象中,格式化程序将只序列化对象的半径字段的值。区域字段中的值不会被序列化,因为非序列化属性已应用于此字段。当我们用Circle c=new Circle(10)的代码构建Circle对象时,在内部,该区域将设置一个大约314.159的值。当序列化此对象时,只有radius (10)字段的值被写入流中,但是当反序列化为Circle对象时,其面积字段的值将被初始化为0,而不是大约314.159的值。为了解决这个问题,定制了一个方法来应用OnDeserializedAttribute属性。此时,的执行过程如下:每次反序列化类型的实例时,格式化程序都将检查类型中是否定义了应用了此属性的方法。如果是,将调用方法,并且调用方法时将正确设置所有可序列化的字段。除了自定义属性onderializationattribute之外,系统还。runtime.serialization命名空间还定义了自定义属性,如onserializadatattribute、onserializadatattribute和onderializationattribute。

实现ISerializable接口来控制序列化和反序列化代码:

使用系统;使用系统。IO;使用系统。运行时。序列化;使用系统。运行时。序列化。格式化程序。二进制;使用系统。安全性。权限;命名空间controlserialization 2 {[Serializable]公共类MyObject : ISerializable { public int n1;公共intn2[非序列化]公共字符串;public MyObject() { }受保护的MyObject(SerializationInfo,StreamingContext上下文){ n1=info。getint 32(' I ');n2=信息。getint 32(' j ');str=信息。getStrIng(' k ');}[SECURITyPermissionattribute(SECURITyAction。Demand,SerializationFormatter=true)]公共虚拟void GetObjectData(SerializationInfo,StreamingContext上下文){ info。AddValue('i ',n1);信息。AddValue('j ',N2);信息。AddValue('k ',字符串);} public void Write() { Console。WriteLine('n1是: ' n1);控制台。WriteLine('n2为: ' N2);控制台。WriteLine(' str is : ' str);} }类Program { static void Main(string[]args){ MyObject obj=new MyObject();obj . n1=2;obj . N2=3;obj.str=' JeffyMemoryStream流=new memory stream();binary formatter=new binary formatter();//将对象序列化到内存流中。在这里,您可以使用从系统抽象类派生的任何类型的对象。这里,我使用内存流类型。格式化程序。序列化(流,对象);小溪。位置=0;obj=nullobj=(MyObject)格式化程序。反序列化(流);物体。write();控制台。read();}}}结果是:

此时的执行过程如下:当格式化程序序列化对象时,它将检查每个对象。如果发现某个对象类型实现了ISerializable接口,格式化程序将忽略所有自定义属性,而是构造一个新的系统。runtime . serialization . serialization info对象,它包含要为该对象实际序列化的值的集合。在序列化信息对象被构造和初始化后,格式化程序调用类型为的GetObjectData方法,并向其传递对序列化信息对象的引用。GetObjectData方法负责决定序列化对象需要哪些信息,并将其添加到SerializationInfo对象中。通过调用AddValue方法添加每一个需要的数据,在添加所有必要的序列化信息之后,它将返回到格式化程序,然后格式化程序将获取所有已经添加到SerializationInfo对象的值,并将其序列化到流中。反序列化时,当格式化程序从流中提取对象时,它将为新对象分配内存。最初,该对象的所有字段都设置为0或空。然后,格式化程序检查该类型是否实现了ISerializable接口。如果此接口存在,格式化程序会尝试调用一个特殊的构造函数,该构造函数的参数与GetObjectData方法的参数完全相同。

4.格式化程序如何序列化和反序列化从上面的分析可以看出,格式化程序主要负责序列化和反序列化。但是,下面是关于格式化程序如何序列化应用了SerializableAttribute属性的对象。

1.格式化程序调用FormatterServices的GetSerializableMembers方法:public static member info[]getserializable members(类型类型,流上下文上下文);此方法使用emission来获取该类型的公共和私有实现字段(用NonSerializedAttributee属性标记的字段除外)。方法返回一个MemberInfo对象数组,其中每个元素对应一个可序列化的实例字段。2.对象被序列化,系统。反射. MemberInfo对象数组被传递给FormatterServices的静态方法getobjectdata:公共静态对象[] getobjectdata (objectobj,memberinfo []成员);此方法返回一个对象数组,其中每个元素标识序列化对象中字段的值。3.格式化程序将程序集标识符和类型的完整名称写入流中。4.然后,格式化程序遍历两个数组中的元素,并将每个成员的名称和值写入流中。下一步是解释格式化程序如何自动反序列化应用了SerializableAttribute属性的对象。

1.格式化程序从流中读取程序集id和完整类型名。2.格式化程序调用FormatterServices的静态方法getuninitializedobject :公共静态对象get uniinitializedobject(type ttype);此方法为新对象分配内存,但不调用该对象的构造函数。但是,对象的所有字段都被初始化为0或空。3格式化程序现在构造并初始化一个MemberInfo数组,并调用FormatterServices的GetSerializableMembers方法,该方法返回一组已序列化且需要反序列化的字段。4.格式化程序根据流中包含的数据创建并初始化对象数组。5.将对新分配的对象、成员信息数组和并行对象数组的引用传递给FormatterServices的静态方法populateobjectmembers :公共静态对象populateobjectmembers(objectobj、成员信息[]成员、对象[]数据);此方法遍历数组,并将每个字段初始化为其相应的值。

注意:格式化如何序列化和反序列化对象是通过C#(第三版)取自CLR,可以帮助初学者进一步了解格式化程序在序列化和反序列化过程中所做的工作。

这篇关于序列化和反序列化的文章终于结束了,希望对朋友们有所帮助。

更多资讯
游戏推荐
更多+