威尼斯人线上娱乐

【威尼斯人线上娱乐】引用类型对象的深拷贝,体系化和反系列化

30 3月 , 2019  

c#中的对象大体分为值类型和引用类型,值类型大约包罗 int, string, struct等,引用类型差不离包含 自定义Class,object 等。

摘要:

C# Serializable

System.SerializableAttribute

串行化是指储存和收获磁盘文件、内部存款和储蓄器或别的地点中的对象。在串行化时,全数的实例数据都封存到存储介质上,在废除串行化时,对象会被恢复生机,且不可能与其原实例差异开来。

只需给类添加Serializable属性,就足以兑现串行化实例的积极分子。

【威尼斯人线上娱乐】引用类型对象的深拷贝,体系化和反系列化。并行化是串行化的逆进度,数据从存款和储蓄介质中读取出来,并赋给类的实例变量。

例:

威尼斯人线上娱乐 1

 1 [Serializable]
 2 public class Person
 3 {
 4     public Person()
 5     {
 6     }
 7 
 8     public int Age;
 9     public int WeightInPounds;
10 }

威尼斯人线上娱乐 2

 

上边来看2个小例子,首先要添加命名空间

using System.Runtime.Serialization.Formatters.Binary;

 

下边包车型大巴代码将对象Person进行系列化并储存到一个文书中

威尼斯人线上娱乐 3

 1 Person me = new Person();
 2 
 3 me.Age = 34;
 4 me.WeightInPounds = 200;
 5 
 6 Stream s = File.Open("Me.dat",FileMode.Create);
 7 
 8 BinaryFormatter bf = new BinaryFormatter();
 9 
10 bf.Serialize(s,me);
11 
12 s.Close();

威尼斯人线上娱乐 4

 

下一场再举贰个并行化的事例

威尼斯人线上娱乐 5

 1 Stream s = File.Open("Me.dat",FileMode.Open);
 2 
 3 BinaryFormatter bf = new BinaryFormatter();
 4 
 5 object o = bf.Deserialize(s);
 6 
 7 Person p = o as Person;
 8 if(p != null)
 9     Console.WriteLine("DeSerialized Person aged:{0} whight:{1}",p.Age,p.WeightInPounds);
10 
11 s.Close();

威尼斯人线上娱乐 6

 

比方须求对一些字段类别化部分不类别化时,大家得以根据如下设置达成

威尼斯人线上娱乐 7

 1 [Serializable]
 2 public class Person
 3 {
 4     public Person()
 5     {
 6     }
 7 
 8     public int Age;
 9     [NonSerialized]
10     public int WeightInPounds;
11 }

威尼斯人线上娱乐 8

 

Serializable在C#中的成效.NET 中的对象系列化
简介
  连串化是指将指标实例的意况存款和储蓄到存款和储蓄媒体的长河。在此进程中,先将指标的共用字段和个人字段以及类的名称(包蕴类所在的程序集)转换为字节流,然后再把字节流写入数据流。在随着对指标开始展览反种类化时,将开创出与原对象完全相同的副本。
威尼斯人线上娱乐 9
 
 在面向对象的条件中完结种类化机制时,必须在易用性和灵活性之间开始展览局部度量。只要你对此进程有丰盛的控制能力,就足以使该进度在非常的大程度上机关举办。
例如,简单的二进制连串化无法满足急需,大概,由于特定原因须要规定类中这么些字段须求连串化。以下各部分将钻探 .NET 框架提供的笃定的类别化学工业机械制,
并注重介绍使您能够依照须要自定义连串化进度的部分至关心珍视要意义。

从始至终存储
 
 大家平时须求将对象的字段值保存到磁盘中,并在后来检索此数据。就算不使用连串化也能做到那项工作,但这种艺术一般很麻烦而且不难失误,并且在须要跟踪
对象的层次结构时,会变得更其复杂。能够设想一下编纂包含大批量对象的特大型业务应用程序的情事,程序员不得不为种种对象编排代码,以便将字段和总体性保存
至磁盘以及从磁盘还原那几个字段和性质。体系化提供了轻松完成这么些目的的高速方法。
威尼斯人线上娱乐 10
 
 公共语言运维时 (CL奥迪Q5) 管理对象在内部存款和储蓄器中的分布,.NET 框架则通过选取反射提供自动的体系化学工业机械制。对象种类化后,类的称呼、程序集以及类实例
的富有数据成员均被写入存款和储蓄媒体中。对象一般用成员变量来囤积对别的实例的引用。类类别化后,体系化引擎将跟踪全体已种类化的引用对象,以担保同等对象不
被连串化多次。.NET 框架所提供的体系化连串布局得以自行正确处理对象图表和巡回引用。对指标图表的唯一须求是,由正在展开类别化的指标所引述的所有对象都必须标记为 Serializable(请参阅基本种类化)。不然,当种类化程序试图类别化未标记的目的时将会出现至极。
威尼斯人线上娱乐 11
  当反连串化已类别化的类时,将重新创建该类,并自行回复全数数据成员的值。

按值封送
 
 对象仅在成立对象的选取程序域中央银立见成效。除非对象是从 马尔斯halByRefObject 派生获得或标志为 Serializable,不然,任何
将对象作为参数字传送递或将其当作结果回到的品味都将失利。假使指标标记为 Serializable,则该指标将被活动种类化,并从四个行使程序域传输至另
3个行使程序域,然后开始展览反连串化,从而在其次个应用程序域中发出出该对象的3个准确无误副本。此进度一般号称按值封送。
威尼斯人线上娱乐 12
 
 若是指标是从 马尔斯halByRefObject 派生获得,则从三个使用程序域传递至另2个应用程序域的是指标引用,而不是指标自小编。也足以将
从 马尔斯halByRefObject 派生得到的对象标记为 Serializable。远程应用此指标时,负责进行系列化并已先行安插为 SurrogateSelector 的格式化程序将控制体系化进度,并用贰个代理替换全数从 马尔斯halByRefObject 派生得到的对
象。要是没有事先安顿为 SurrogateSelector,类别化体系布局将遵守上边包车型客车专业连串化规则(请参阅种类化进程的步调)。

 

中央连串化
  要使一个类可系列化,最简易的点子是运用 Serializable 属性对它进行标记,如下所示:

威尼斯人线上娱乐 13

1 [Serializable]
2 public class MyObject 
3 {
4    public int n1 = 0;
5    public int n2 = 0;
6    public String str = null;
7 }

威尼斯人线上娱乐 14

  以下代码片段表达了怎么将该类的2个实例连串化为一个文书:

威尼斯人线上娱乐 15

1 MyObject obj = new MyObject();
2 obj.n1 = 1;
3 obj.n2 = 24;
4 obj.str = "一些字符串";
5 IFormatter formatter = new BinaryFormatter();
6 Stream stream = new FileStream("MyFile.bin", FileMode.Create,
7 FileAccess.Write, FileShare.None);
8 formatter.Serialize(stream, obj);
9 stream.Close();

威尼斯人线上娱乐 16

  本例使用二进制格式化程序举行种类化。您只需创造八个要动用的流和格式化程序的实例,然后调用格式化程序的 塞里alize 方法。流和要种类化的对象实例作为参数提需求此调用。类中的全体成员变量(甚至标记为 private 的变量)都将被类别化,但这点在本例中未明显展现出来。在那一点上,二进制类别化不相同于只种类化公共字段的 XML 类别化程序。
威尼斯人线上娱乐 17
  将目的还原到它原先的景况也十一分不难。首先,创设格式化程序和流以进行读取,然后让格式化程序对目的开始展览反系列化。以下代码片段表达了什么开展此操作。

威尼斯人线上娱乐 18

 1 IFormatter formatter = new BinaryFormatter();
 2 Stream stream = new FileStream("MyFile.bin", FileMode.Open,
 3 FileAccess.Read, FileShare.Read);
 4 MyObject obj = (MyObject) formatter.Deserialize(fromStream);
 5 stream.Close();
 6 
 7 // 下面是证明
 8 Console.WriteLine("n1: {0}", obj.n1);
 9 Console.WriteLine("n2: {0}", obj.n2);
10 Console.WriteLine("str: {0}", obj.str);

威尼斯人线上娱乐 19

  下面所利用的 BinaryFormatter 功用很高,能生成那些严密的字节流。全体应用此格式化程序系列化的对
象也可采取它实行反体系化,对于体系化将在 .NET 平台上拓展反种类化的靶子,此格式化程序无疑是3个一语双关术工作具。要求留意的是,对目的举行反系列化时
并不调用构造函数。对反类别化添加那项约束,是出于品质方面包车型地铁设想。但是,那违背了目的编写者平日选用的一部分运作时约定,因而,开发职员在将对象标记为可
系列化时,应确认保障考虑了这一特殊约定。
威尼斯人线上娱乐 20
  若是须要具备可移植性,请使用 SoapFormatter。所要做的改变只是将以上代码中的格式化程序换来 SoapFormatter,而 Serialize 和 Deserialize 调用不变。对于地点使用的言传身教,该格式化程序将转变以下结果。

威尼斯人线上娱乐 21

<SOAP-ENV:Envelope
   xmlns:xsi=http://www.w3.org/2001/XMLSchema-instance
   xmlns:xsd="http://www.w3.org/2001/XMLSchema"
   xmlns:SOAP- ENC=http://schemas.xmlsoap.org/soap/encoding/
   xmlns:SOAP- ENV=http://schemas.xmlsoap.org/soap/envelope/
   SOAP-ENV:encodingStyle=
   "http://schemas.microsoft.com/soap/encoding/clr/1.0
  http://schemas.xmlsoap.org/soap/encoding/"
   xmlns:a1="http://schemas.microsoft.com/clr/assem/ToFile">

   <SOAP-ENV:Body>
     <a1:MyObject id="ref-1">
       <n1>1</n1>
       <n2>24</n2>
       <str id="ref-3">一些字符串</str>
     </a1:MyObject>
   </SOAP-ENV:Body>
</SOAP-ENV:Envelope>

威尼斯人线上娱乐 22

  需求注意的是,一点都不大概持续 Serializable 属性。假如从 MyObject 派生出一个新的类,则那一个新的
类也必须利用该属性实行标记,不然将相当的小概类别化。例如,假设打算体系化以下类实例,将会显得五个 SerializationException,表明 MyStuff 类型未标记为可系列化。

1 public class MyStuff : MyObject
2 {
3    public int n3;
4 }

  使用连串化属性非凡有益,不过它存在上述的片段范围。有关何时标记类以进行种类化(因为类编译后就无法再种类化),请参见有关证实(请参阅上面包车型大巴类别化规则)。

 

选择性种类化
 
 类常常包蕴不应被体系化的字段。例如,假诺某些类用一个分子变量来存款和储蓄线程 ID。当此类被反类别化时,系列化此类时所蕴藏的 ID 对应的线程或者不
再运维,所以对那么些值实行种类化没有意思。可以因而采取 NonSerialized 属性标记成员变量来防备它们被类别化,如下所示:

威尼斯人线上娱乐 23

1 [Serializable]
2 public class MyObject
3 {
4     public int n1;
5     [NonSerialized] public int n2;
6     public String str;
7 }

威尼斯人线上娱乐 24

 

自定义类别化
 
 能够经过在目的上贯彻 ISerializable 接口来自定义种类化进程。这一效果在反种类化后成员变量的值失效时越发有用,但是急需为变量提供值
以重建对象的全体气象。要完毕 ISerializable,需求达成 GetObjectData 方法以及三个出奇的构造函数,在反种类化对象时要用
到此构造函数。以下代码示例表明了怎么着在前一部分中关系的 MyObject 类上落到实处 ISerializable。

威尼斯人线上娱乐 25

 1 [Serializable]
 2 public class MyObject : ISerializable
 3 {
 4     public int n1;
 5     public int n2;
 6     public String str;
 7 
 8     public MyObject()
 9     {
10     }
11 
12     protected MyObject(SerializationInfo info, StreamingContext context)
13     {
14         n1 = info.GetInt32("i");
15         n2 = info.GetInt32("j");
16         str = info.GetString("k");
17     }
18 
19     public virtual void GetObjectData(SerializationInfo info,
20                                       StreamingContext context)
21     {
22         info.AddValue("i", n1);
23         info.AddValue("j", n2);
24         info.AddValue("k", str);
25     }
26 }

威尼斯人线上娱乐 26

  在连串化进度中调用 GetObjectData 时,需求填写方法调用中提供的 SerializationInfo 对象。只需按名称/值
对的款式丰盛将要体系化的变量。其名称能够是别的公文。只要已体系化的多寡足以在反连串化进程中回复对象,便能够自由选用添加
至 SerializationInfo 的分子变量。如若基对象实现了 ISerializable,则派生类应调用其基对象
的 GetObjectData 方法。
威尼斯人线上娱乐 27
 
 需求强调的是,将 ISerializable 添加至某些类时,要求同时完毕 GetObjectData 以及新鲜的构造函数。假设缺少 GetObjectData,编写翻译器将时有发生警告。可是,由于不大概强制完毕构造函数,所以,缺乏构造函数时不会发生警告。固然在未曾构造函数的图景下尝
试反类别化有个别类,将会出现卓殊。在排除潜在安全性和版本控制难题等地点,当前规划优化 SetObjectData 方法。例如,要是将 SetObjectData 方法定义为某些接口的一有个别,则此格局必须是公家措施,那使得用户只可以编写代码来预防反复调
用 SetObjectData 方法。能够设想,假使有些对象正在实践有些操作,而某些恶意应用程序却调用此目标的 SetObjectData 方
法,将会挑起局地私人住房的辛勤。
威尼斯人线上娱乐 28
  在反系列化进程中,使用出于此目标而提供的构造函数将 SerializationInfo 传递给类。对象反连串化时,对构造函数的别样可知性约束都将被忽略,因而,能够将类标志为 public、protected、internal 或 private。3个不易的章程是,在类未封装的景色下,将构造函数标记为 protect。假若类已打包,则应标记为 private。要还原对象的情形,只需利用体系化时采取的称号,从 SerializationInfo 中找找变量的值。倘使基类完结了 ISerializable,则应调用基类的构造函数,以使基础对象能够还原其变量。
威尼斯人线上娱乐 29
  要是从贯彻了 ISerializable 的类派生出一个新的类,则只要新的类中包涵其余索要系列化的变量,就亟须同时完结构造函数以及 GetObjectData 方法。以下代码片段展现了怎么利用上文所示的 MyObject 类来达成此操作。

威尼斯人线上娱乐 30

 1 [Serializable]
 2 public class ObjectTwo : MyObject
 3 {
 4     public int num;
 5 
 6     public ObjectTwo() : base()
 7     {
 8     }
 9 
10     protected ObjectTwo(SerializationInfo si, StreamingContext context) :
11         base(si,context)
12     {
13         num = si.GetInt32("num");
14     }
15 
16     public override void GetObjectData(SerializationInfo si,
17                                        StreamingContext context)
18     {
19         base.GetObjectData(si,context);
20         si.AddValue("num", num);
21     }
22 }

威尼斯人线上娱乐 31

  切记要在反类别化构造函数中调用基类,不然,将永生永世不会调用基类上的构造函数,并且在反连串化后也无从营造完全的指标。
威尼斯人线上娱乐 32
 
 对象被彻底重新创设,不过在反连串化进程中调用方法恐怕会带来不良的副功效,因为被调用的格局大概引用了在调用时未尝反种类化的靶子引用。假若正在开始展览反种类化的类实现了 IDeserializationCallback,则反类别化整个对象图表后,将自行调用 OnSerialization 方
法。此时,引用的全部子对象均已通通恢复。某个类不使用上述事件侦听器,很难对它们举行反系列化,散列表就是一个顶尖的例证。在反种类化进程中找找关键字/值对分外简单,然而,由于不恐怕保险从散列表派生出的类已反种类化,所以把那几个指标添加回散列表时会并发有的难题。由此,建议近来毫无在散列表上调用方法。
威尼斯人线上娱乐 33
体系化进程的步骤
  在格式化程序上调用 Serialize 方法时,对象系列化遵照以下规则举行:
威尼斯人线上娱乐 34
  检查格式化程序是还是不是有代理选用器。若是有,检查代理接纳器是还是不是处理钦定项指标对象。假设选择器处理此目的类型,将在代理采取器上调用 ISerializable.GetObjectData。
  假设没有代理选用器或有却不处理此类型,将检查是或不是使用 Serializable 属性对指标开始展览标记。借使未标记,将会掀起 SerializationException。
  假使目的已被正确标记,将检核对象是或不是落到实处了 ISerializable。若是已落到实处,将在对象上调用 GetObjectData。
  假诺指标未兑现 塞里alizable,将运用暗中同意的连串化策略,对负有未标记为 NonSerialized 的字段都实行连串化。
  版本控制
 
 .NET 框架帮忙版本控制和并排执行,并且,即使类的接口保持一致,全数类均可跨版本工作。由于类别化涉及的是成员变量而非接口,所以,在向要跨版本
类别化的类中添加成员变量,或从中删除变量时,应谨慎行事。尤其是对此未达成 ISerializable 的类更应那样。若当前版本的情状发生了任何变
化(例如添加成员变量、更改变量类型或改变变量名称),都意味一旦同样类型的存活对象是运用最初版本举办系列化的,则无从得逞对它们举办反体系化。
威尼斯人线上娱乐 35
  就算目的的动静必要在不一样版本间爆发变动,类的作者能够有二种选用:
威尼斯人线上娱乐 36
  达成 I塞里alizable。那使你能够规范地决定类别化和反连串化进程,在反连串化进度中正确地增进和说明未来景观。
  使用 NonSerialized 属性标记不重庆大学的积极分子变量。仅当预测类在不相同版本间的转变较小时,才可应用那些选项。例如,把1个新变量添加至类的较高版本后,能够将该变量标记为 NonSerialized,以确认保证该类与早期版本保持分外。

种类化规则
 
 由于类编写翻译后便不可能连串化,所以在统一筹划新类时应考虑连串化。须要考虑的难点有:是或不是必须跨应用程序域来发送此类?是或不是要远程应用此类?用户将怎么着利用此
类?也许他们会从小编的类中派生出三个内需体系化的新类。只要有那种或许性,就应将类标志为可系列化。除下列情况以外,最佳将全部类都标志为可系列化:
威尼斯人线上娱乐 37
  全数的类都永远也不会超越应用程序域。要是有些类不要求连串化但供给跨越应用程序域,请从 马尔斯halByRefObject 派生此类。
  类存款和储蓄仅适用于其眼下实例的万分指针。例如,假诺有个别类富含非受控的内部存款和储蓄器或文件句柄,请确认保障将这一个字段标记为 NonSerialized 或根本不体系化此类。
  某个数据成员蕴涵敏感消息。在那种意况下,建议落到实处 I塞里alizable 并仅系列化所要求的字段。 

转自:

1.AdminUserInfo.cs

值类型直接存款和储蓄对象,而引用类型存款和储蓄对象的地方,在对引用类型进行复制的时候,也只是复制对象的地址。

何以要运用种类化?

[Serializable]队列化类——System.SerializableAttribute

全然复制一个引用类型对象首要有二种方法:

1.额外添加四个构造函数,入参为待复制对象(倘诺字段为引用类型,必要一而再添加构造函数,那样处境会变的十分复杂。)

    public class Test1
    {
        private int field1;
        private int field2;
        private int field3;
        public Test1()
        { 

        }

        public Test1(Test1 test1)
        {
            this.field1 = test1.field1;
            this.field2 = test1.field2;
            this.field3 = test1.field3;
        }
    }

2.选取连串化反系列化(对质量会有杀伤)

using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Runtime.Serialization.Formatters.Binary;
using System.Text;
using System.Threading.Tasks;

namespace Test
{
    class Program
    {
        static void Main(string[] args)
        {
            Test t1 = new Test();
            Console.WriteLine(t1.list.Count);
            Test t2 = (Test)Clone(t1);
            t2.list.Add("");
            Console.WriteLine(t2.list.Count);
            Console.WriteLine(t1.list.Count);
            Console.ReadLine();
        }

        public static object Clone(object obj)
        {
            BinaryFormatter bf = new BinaryFormatter();
            MemoryStream ms = new MemoryStream();
            bf.Serialize(ms, obj);
            ms.Position = 0;
            return (bf.Deserialize(ms)); ;
        }
    }

    [Serializable]
    public class Test
    {
        public List<string> list = new List<string>();
    }
}

3.利用反射(测试了三个网上的接口可用,可是对品质杀伤和类别化反系列化卓殊,而且对代码混淆有自然影响。 
 

最要害的四个原因是:

串行化是指储存和获取磁盘文件、内部存款和储蓄器或别的地点中的对象。在串行化时,全数的实例数据都保留到存款和储蓄介质上,在撤废串行化时,对象会被还原,且不可能与其原实例区别开来。

1.     
将目的的景况保存在存款和储蓄媒体中以便可以在此后再一次创立出完全相同的副本;

只需给类添加Serializable属性,就能够兑现串行化实例的分子。

2.     
按值将指标从三个应用程序域发送至另一个应用程序域。

并行化是串行化的逆进程,数据从存款和储蓄介质中读取出来,并赋给类的实例变量。

譬如说,体系化可用以在 ASP.NET
中保存会话状态,以及将对象复制到 Windows
窗体的剪贴板中。

例:

它还可用来按值将对象从1个运用程序域远程传递至另三个行使程序域。

 

本文简要介绍了 Microsoft .NET
中选择的系列化。

1 [Serializable]
2 public class Person
3 {
4 public Person()
5 {
6 }
7
8 public int Age;
9 public int WeightInPounds;
10 }

 

一、        简介

using System.Runtime.Serialization.Formatters.Binary;

 

上边包车型地铁代码将对象Person进行连串化并储存到1个文书中

类别化是指将目的实例的事态存款和储蓄到存款和储蓄媒体的历程。

 

在此进度中,

1 Person me = new Person();
2
3 me.Age = 34;
4 me.WeightInPounds = 200;
5
6 Stream s = File.Open("Me.dat",FileMode.Create);
7
8 BinaryFormatter bf = new BinaryFormatter();
9
10 bf.Serialize(s,me);
11
12 s.Close();

1.     
先将对象的国有字段和私家字段以及类的称谓(包罗类所在的程序集)转换为字节流,

 

2.      然后再把字节流写入数据流。

然后再举一个并行化的例证

3.     
在随之对指标实行反种类化时,将开创出与原对象完全相同的副本。

Stream s = File.Open("Me.dat",FileMode.Open);

BinaryFormatter bf = new BinaryFormatter();

object o = bf.Deserialize(s);

Person p = o as Person;
if(p != null)
Console.WriteLine("DeSerialized Person aged:{0} whight:{1}",p.Age,p.WeightInPounds);

s.Close();

在面向对象的条件中贯彻连串化学工业机械制时,必须在易用性和灵活性之间展开一些权衡。

 

就算您对此进度有丰盛的控制能力,就能够使该进程在十分大程度上自行进行。例如,简单的二进制种类化不可能满意急需,也许,由于特定原因必要规定类中那多少个字段需求类别化。

一经需要对部分字段连串化部分不连串化时,大家得以依照如下设置完成

以下各部分将研讨 .NET
框架提供的保证的种类化学工业机械制,并重视介绍使您能够根据须求自定义连串化进程的局地根本效能。

[Serializable]
public class Person
{
public Person()
{
}

public int Age;
[NonSerialized]
public int WeightInPounds;
}

② 、         持久存款和储蓄

大家日常索要将指标的字段值保存到磁盘中,并在后来检索此数据。

就算不使用种类化也能完毕那项工作,但那种方法一般很麻烦而且便于失误,并且在须要跟踪对象的层次结构时,会变得更其复杂。

能够想像一下编写制定包括大批量对象的重型业务应用程序的图景,程序员不得不为每1个对象编排代码,以便将字段和总体性保存至磁盘以及从磁盘还原那些字段和性质。

类别化提供了轻松达成这一个目的的快速方法。

公家语言运维时 (CL昂科威)
管理对象在内部存款和储蓄器中的分布,.NET
框架则透过利用反射提供自动的体系化机制。

指标种类化后,类的名号、程序集以及类实例的有所数据成员均被写入存款和储蓄媒体[正文中的存款和储蓄媒体是什么?xml?]中。

目的日常用成员变量来储存对其余实例的引用。类体系化后,类别化引擎将跟踪全数已连串化的引用对象,以保险同等对象不被类别化多次[连串化是对准对象的?这岂不是三个顺序会须求过多的连串化?]。

.NET
框架所提供的类别化种类布局得以自行正确处理对象图表和巡回引用。

对目的图表[怎么是指标图表?]的唯一须要是,由正在拓展种类化的靶子所引用的具有指标都不可能不标记为
Serializable(请参阅主干系列化)。不然,当连串化程序试图体系化未标记的指标时将会出现卓殊。

当反种类化已种类化的类时,将重新创建该类,并活动恢复生机全数数据成员的值。

 Serializable在C#中的效率.NET 中的对象连串化
威尼斯人线上娱乐 38
威尼斯人线上娱乐 39简介
威尼斯人线上娱乐 40系列化是指将目的实例的气象存款和储蓄到存储媒体的经过。在此进程中,先将指标的集体字段和民用字段以及类的名号(包罗类所在的程序集)转换为字节流,然后再把字节流写入数据流。在跟着对目的开始展览反体系化时,将成立出与原对象完全相同的副本。
威尼斯人线上娱乐 41
威尼斯人线上娱乐 42在面向对象的条件中落到实处系列化机制时,必须在易用性和灵活性之间进行部分度量。只要你对此进度有足够的控制能力,就足以使该进度在相当的大程度上机关实行。例如,不难的二进制类别化不能够知足急需,也许,由于特定原因须求规定类中那么些字段需求体系化。以下各部分将探索 .NET 框架提供的保障的类别化学工业机械制,一视同仁点介绍使您能够依照需求自定义连串化进度的片段关键功用。
威尼斯人线上娱乐 43
威尼斯人线上娱乐 44慎始而敬终存款和储蓄
威尼斯人线上娱乐 45我们日常要求将对象的字段值保存到磁盘中,并在后来检索此数据。就算不使用类别化也能做到那项工作,但这种方式一般很麻烦而且简单失误,并且在须要跟踪对象的层次结构时,会变得愈加复杂。能够设想一下编纂包括多量对象的巨型业务应用程序的气象,程序员不得不为每1个对象编排代码,以便将字段和性质量保证存至磁盘以及从磁盘还原那些字段和本性。类别化提供了轻松落成那个目标的迅猛方法。
威尼斯人线上娱乐 46
威尼斯人线上娱乐 47公物语言运营时 (CLSportage) 管理对象在内部存款和储蓄器中的分布,.NET 框架则经过动用反射提供自动的类别化学工业机械制。对象体系化后,类的称谓、程序集以及类实例的拥有数据成员均被写入存款和储蓄媒体中。对象经常用成员变量来存款和储蓄对任何实例的引用。类系列化后,种类化引擎将跟踪全部已体系化的引用对象,以保障同等对象不被连串化数次。.NET 框架所提供的系列化种类布局可以自动正确处理对象图表和巡回引用。对指标图表的唯一需求是,由正在实行连串化的对象所引述的有着目的都必须标记为 Serializable(请参阅基本体系化)。不然,当连串化程序试图系列化未标记的靶申时将会出现至极。
威尼斯人线上娱乐 48
威尼斯人线上娱乐 49当反体系化已连串化的类时,将再一次创建该类,并自行还原全部数据成员的值。
威尼斯人线上娱乐 50
威尼斯人线上娱乐 51按值封送
威尼斯人线上娱乐 52对象仅在创制对象的施用程序域中有效。除非对象是从 马尔斯halByRefObject 派生获得或标志为 Serializable,不然,任何将对象作为参数字传送递或将其视作结果回到的品尝都将退步。若是目的标记为 Serializable,则该指标将被电动类别化,并从二个应用程序域传输至另一个利用程序域,然后开始展览反连串化,从而在其次个使用程序域中爆发出该对象的八个准儿副本。此进程一般号称按值封送。
威尼斯人线上娱乐 53
威尼斯人线上娱乐 54一经指标是从 马尔斯halByRefObject 派生得到,则从三个运用程序域传递至另二个行使程序域的是目的引用,而不是指标自笔者。也得以将从 马尔斯halByRefObject 派生获得的靶子标记为 Serializable。远程应用此目的时,负责实行体系化并已先期布署为 SurrogateSelector 的格式化程序将决定连串化进程,并用2个代理替换全数从 马尔斯halByRefObject 派生获得的靶子。倘若没有先行安排为 SurrogateSelector,种类化种类布局将服从上面包车型客车专业类别化规则(请参阅连串化进度的步骤)。
威尼斯人线上娱乐 55
威尼斯人线上娱乐 56中央连串化
威尼斯人线上娱乐 57要使3个类可种类化,最容易易行的点子是选择 Serializable 属性对它举办标记,如下所示:
威尼斯人线上娱乐 58

三 、        按值封送

指标仅在创立对象的行使程序域中有效。除非对象是从 MarshalByRefObject
派生获得或标志为 Serializable,不然,任何将指标作为参数字传送递或将其看作结果重临的品尝都将破产。

万一目的标记为 Serializable[怎么样标记为Serializable],则该对象将被电动系列化,并从贰个采用程序域传输至另2个用到程序域,然后实行反连串化,从而在其次个使用程序域中生出出该指标的一个准确副本。此进度一般号称按值封送

要是指标是从 MarshalByRefObject
派生获得,则从1个使用程序域传递至另一个使用程序域的是指标引用,而不是目的自笔者。

也得以将从 MarshalByRefObject 派生获得的对象标记为 Serializable

长距离应用此指标时,负责进行连串化并已先行安排为 SurrogateSelector
的格式化程序将决定种类化进程,并用1个代理替换全体从 MarshalByRefObject
派生得到的靶子。借使没有先行布署为 SurrogateSelector,系列化种类布局将信守上边包车型大巴正式种类化规则(请参阅体系化进程的手续)。

[Serializable]
public class MyObject {
   public int n1 = 0;
   public int n2 = 0;
   public String str = null;
}

肆 、        基本系列化

要使多个类可类别化,最不难易行的艺术是使用 Serializable 属性[为啥webservice中从未标记Serializable?]

对它举办标记,如下所示:

[Serializable]

 public class MyObject {

  public int n1 = 0;

  public int n2 = 0;

  public String str = null;

}

以下代码片段表明了怎么将此类的二个实例连串化为一个文书[咱俩不必要用手写那个代码吧?]:

MyObject obj = new MyObject();

obj.n1 = 1;

obj.n2 = 24;

obj.str = “一些字符串”;

威尼斯人线上娱乐,IFormatter formatter = new BinaryFormatter();

Stream stream = new FileStream(“MyFile.bin”,
FileMode.Create,

FileAccess.Write, FileShare.None);

formatter.Serialize(stream, obj);

stream.Close();

本例使用二进制格式化程序开始展览体系化。

您只需创立1个要使用的流和格式化程序的实例,然后调用格式化程序的 Serialize
方法。流和要体系化的目的实例作为参数提须求此调用。

类中的全体成员变量(甚至标记为 private
的变量)都将被连串化,但那一点在本例中未显然展现出来。

在那或多或少上,二进制连串化不一样于只体系化公共字段的 XML
体系化程序[共有多少种系列化?二进制连串化和xml体系化分别用在如啥地方方?二进制/XML是还是不是正是本文所说的蕴藏媒体?]。

将对象还原到它原先的气象也分外不难。

率先,创设格式化程序和流以拓展读取,

下一场让格式化程序对目标开始展览反种类化。

以下代码片段表达了哪些进行此操作。

IFormatter formatter = new BinaryFormatter();

Stream stream = new FileStream(“MyFile.bin”,
FileMode.Open,

FileAccess.Read, FileShare.Read);

MyObject obj = (MyObject)
formatter.Deserialize(fromStream);

stream.Close();

 

// 上边是印证

Console.WriteLine(“n1: {0}”, obj.n1);

Console.WriteLine(“n2: {0}”, obj.n2);

Console.WriteLine(“str: {0}”, obj.str);

地点所使用的 BinaryFormatter 功能很高,能生成那一个紧密的字节流。

不无应用此格式化程序连串化的对象也可采用它实行反系列化,对于系列化将在 .NET
平台上进展反类别化的对象,此格式化程序无疑是3个妙不可言工具。

亟待注意的是,对指标开始展览反类别化时并不调用构造函数[不调用构造函数,会不会为编制程序带来影响,例如不能够在构造函数中添加逻辑?照旧,不要求关爱构造函数,因为对象的变量足以表明对象的情况?]。对反连串化添加那项约束,是出于品质方面包车型客车设想[不调用构造函数?者对品质会有多大影响,这么说调用构造函数并不是完全没有必要?]。不过,这违背了对象编写者经常选择的局地周转时约定,由此,开发职员在将对象标记为可连串化时,应确认保证考虑了这一异样约定。

借使供给具有可移植性,请使用 SoapFormatter。所要做的改变只是将上述代码中的格式化程序换来
SoapFormatter,而 SerializeDeserialize 调用不变。

对此地点运用的以身作则,该格式化程序将扭转以下结果。

<SOAP-ENV:Envelope

 
xmlns:xsi=

  xmlns:xsd=””

  xmlns:SOAP-
ENC=

  xmlns:SOAP-
ENV=

  SOAP-ENV:encodingStyle=

 

  “

 
xmlns:a1=”;

 

  <SOAP-ENV:Body>

    <a1:MyObject id=”ref-1″>

      <n1>1</n1>

      <n2>24</n2>

      <str id=”ref-3″>一些字符串</str>

    </a1:MyObject>

  </SOAP-ENV:Body>

</SOAP-ENV:Envelope>

必要专注的是,不能继承 Serializable 属性。如果从 MyObject
派生出3个新的类,则那些新的类也务必利用该属性举办标记,不然将非常的小概系列化。[如果Serializable
属性无法一而再,为啥webservice类中尚无安装Serializable 属性?]

例如,假设准备体系化以下类实例,将会展现2个 SerializationException,说明 MyStuff
类型未标记为可系列化。

public class MyStuff : MyObject

{

  public int n3;

}

运用种类化属性格外方便,然而它存在上述的一对限量。

关于哪一天标记类以进行连串化(因为类编写翻译后就无法再连串化),请参考有关表明(请参阅上边包车型大巴系列化规则)。

威尼斯人线上娱乐 59以下代码片段表达了怎样将此类的3个实例系列化为多个文书:
威尼斯人线上娱乐 60

五 、        选取性体系化

类一般包蕴不应被种类化的字段。例如,假使有个别类用二个分子变量来存款和储蓄线程 ID。当此类被反类别化时,种类化此类时所蕴藏的 ID
对应的线程恐怕不再运维,所以对这一个值进行体系化没有意义。

能够通过应用 NonSerialized 属性标记成员变量来幸免它们被种类化,如下所示:

[Serializable]

public class MyObject

{

  public int n1;

  [NonSerialized] public int n2;

  public String str;

}

MyObject obj = new MyObject();
obj.n1 = 1;
obj.n2 = 24;
obj.str = "一些字符串";
IFormatter formatter = new BinaryFormatter();
Stream stream = new FileStream("MyFile.bin", FileMode.Create,
FileAccess.Write, FileShare.None);
formatter.Serialize(stream, obj);
stream.Close();

六 、        自定义系列化

能够因此在指标上贯彻 ISerializable 接口来自定义体系化进程[自定义系列化进程是何许,自身写代码连串化,反连串化对象?]。

这一效益在反类别化后成员变量的值失效时尤其有用,可是急需为变量提供值以重建对象的完全气象。

要实现 ISerializable,要求实现 GetObjectData
方法以及贰个新鲜的构造函数[不是反类别化的时候,不调用构造函数吗?],在反序列化对象时要用到此构造函数。

以下代码示例表明了如何在前一部分中涉及的 MyObject 类上贯彻
ISerializable

[Serializable]

public class MyObject : ISerializable

{

  public int n1;

  public int n2;

  public String str;

 

  public MyObject()

  {

  }

 

  protected MyObject(SerializationInfo info,
StreamingContext context)

  {

    n1 = info.GetInt32(“i”);

    n2 = info.GetInt32(“j”);

    str = info.GetString(“k”);

  }

 

  public virtual void GetObjectData(SerializationInfo
info,

StreamingContext context)

  {

    info.AddValue(“i”, n1);

    info.AddValue(“j”, n2);

    info.AddValue(“k”, str);

  }

}

在体系化进度中调用 GetObjectData 时,必要填写方法调用中提供的 SerializationInfo
对象。只需按名称/值对的款型丰富将要类别化的变量。其名称能够是别的文件。只要已连串化的数目足以在反体系化进程中回复对象,便足以自由选用添加至
SerializationInfo
的成员变量。假若基对象达成了 ISerializable,则派生类应调用其基对象的 GetObjectData 方法。

供给强调的是,将 ISerializable 添加至某些类时,要求同时实现 GetObjectData
以及特殊的构造函数。借使贫乏 GetObjectData,编写翻译器将发出警告。可是,由于不可能强制完成构造函数,所以,缺少构造函数时不会产生警示。假设在未曾构造函数的情况下品尝反种类化某些类,将会出现至极。

在破除潜在安全性和版本控制难题等地点,当前统一筹划优于 SetObjectData
方法。例如,如果将 SetObjectData
方法定义为有些接口的一片段,则此方式必须是国有措施,那使得用户只好编写代码来防护频仍调用
SetObjectData
方法。能够想像,假若某些对象正在举行有些操作,而某些恶意应用程序却调用此指标的
SetObjectData
方法,将会滋生部分私人住房的劳动。

在反种类化进度中,使用出于此目标而提供的构造函数将 SerializationInfo
传递给类。对象反连串化时,对构造函数的任何可见性约束都将被忽视,由此,能够将类标志为 public、protected、internal 或 private。

1个不错的点子是,在类未封装的场地下,将构造函数标记为 protect。假如类已打包,则应标记为
private。要过来对象的景色,只需采纳种类化时选用的名号,从 SerializationInfo
中检索变量的值。尽管基类落成了 ISerializable,则应调用基类的构造函数,以使基础对象能够还原其变量。

假设从完毕了 ISerializable
的类派生出贰个新的类,则只要新的类中包含其余要求连串化的变量,就务须同时落到实处构造函数以及
GetObjectData
方法。

以下代码片段展现了哪些运用上文所示的 MyObject
类来形成此操作。

[Serializable]

public class ObjectTwo : MyObject

{

  public int num;

 

  public ObjectTwo() : base()

  {

  }

 

  protected ObjectTwo(SerializationInfo si,
StreamingContext context) :

base(si,context)

  {

    num = si.GetInt32(“num”);

  }

 

  public override void
GetObjectData(SerializationInfo si,

StreamingContext context)

  {

    base.GetObjectData(si,context);

    si.AddValue(“num”, num);

  }

}

记住要在反体系化构造函数中调用基类,不然,将永久不会调用基类上的构造函数,并且在反系列化后也无能为力营造完整的指标。

目的被彻底重新营造,然而在反种类化进程中调用方法可能会拉动不良的副功用,因为被调用的法子大概引用了在调用时不曾反体系化的对象引用[不亮堂哪些意思?是现阶段目的,照旧其余对象?]。

借使正在拓展反系列化的类达成了 DeserializationCallback,则反种类化整个对象图表后,将自行调用
OnSerialization
方法。此时,引用的所有子对象均已全然恢复生机。

稍加类不利用上述事件侦听器,很难对它们实行反系列化,散列表[何以是散列表?]就是二个卓绝的例子。

在反系列化进程中搜寻关键字/值对十分简单,可是,由于无法担保从散列表派生出的类已反种类化,所以把这个目的添加回散列表时相会世有的难题。由此,建议如今不用在散列表上调用方法。

威尼斯人线上娱乐 61本例使用二进制格式化程序开始展览连串化。您只需创设贰个要采纳的流和格式化程序的实例,然后调用格式化程序的 Serialize 方法。流和要连串化的靶子实例作为参数提供给此调用。类中的全数成员变量(甚至标记为 private 的变量)都将被类别化,但那点在本例中未显明体现出来。在那一点上,二进制连串化分裂于只体系化公共字段的 XML 类别化程序。
威尼斯人线上娱乐 62
威尼斯人线上娱乐 63将指标还原到它原先的情景也相当简单。首先,制造格式化程序和流以开展读取,然后让格式化程序对指标开始展览反连串化。以下代码片段表达了什么样进展此操作。
威尼斯人线上娱乐 64

七 、        体系化进度的步子

在格式化程序上调用 Serialize 方法时,对象类别化依据以下规则进行:

  • 检查格式化程序是还是不是有代理选择器[是还是不是系列化的靶子中所引用的对象都不能够不是可连串化的指标,不然不能够反连串化。那么,是还是不是webservice不能引用未系列化的对象?]。若是有,检查代理选择器是或不是处理钦点项目标目的。就算选择器处理此指标类型,将在代理选用器上调用
    ISerializable.GetObjectData
  • 即使没有代理选择器或有却不处理此类型,将检查是否选拔 Serializable
    属性对指标开始展览标记。假若未标记,将会吸引 SerializationException

  • 若果指标已被正确标记,将检核查象是不是贯彻了 ISerializable。假如已落到实处,将在指标上调用
    GetObjectData

  • 假定指标未落实 Serializable,将应用默许的系列化策略,对具有未标记为
    NonSerialized
    的字段都进展系列化。

IFormatter formatter = new BinaryFormatter();
Stream stream = new FileStream("MyFile.bin", FileMode.Open,
FileAccess.Read, FileShare.Read);
MyObject obj = (MyObject) formatter.Deserialize(fromStream);
stream.Close();

// 下面是证明
Console.WriteLine("n1: {0}", obj.n1);
Console.WriteLine("n2: {0}", obj.n2);
Console.WriteLine("str: {0}", obj.str);

捌 、        版本控制

.NET
框架匡助版本控制和并排执行,并且,借使类的接口保持一致,全部类均可跨版本工作。

鉴于系列化涉及的是成员变量而非接口,所以,在向要跨版本连串化的类中添加成员变量,或从中删除变量时,应严格行事。尤其是对于未兑现
ISerializable
的类更应这么。

若当前版本的情事产生了任何变化(例如添加成员变量、更改变量类型或转移变量名称),都意味如果一致种类的共处对象是使用最初版本实行体系化的,则不能够成功对它们实行反系列化。

只要指标的图景供给在不相同版本间产生变更,类的撰稿人能够有三种采纳:

  • 实现 ISerializable。那使您能够确切地控制种类化和反类别化进程,在反连串化进度中国科高校学地抬高和分解现在情形。
  • 使用 NonSerialized
    属性标记不主要的积极分子变量。仅当预测类在不一致版本间的成形较刻钟,才可采纳这几个选项。例如,把一个新变量添加至类的较高版本后,能够将该变量标记为
    NonSerialized,以担保该类与中期版本保持包容[体系化对象中涵盖NonSerialized标记,是否有隐患?]。

威尼斯人线上娱乐 65下边所使用的 BinaryFormatter 效率很高,能生成这么些紧凑的字节流。全体应用此格式化程序系列化的对象也可利用它举办反类别化,对于体系化将在 .NET 平台上海展览中心开反类别化的靶子,此格式化程序无疑是2个精粹工具。要求专注的是,对目的进行反体系化时并不调用构造函数。对反系列化添加那项约束,是出于质量方面的设想。但是,那违背了目的编写者平常采取的一些运行时约定,因而,开发职员在将对象标记为可种类化时,应确定保障考虑了这一奇异约定。
威尼斯人线上娱乐 66
威尼斯人线上娱乐 67一经要求具有可移植性,请使用 SoapFormatter。所要做的变更只是将上述代码中的格式化程序换到 SoapFormatter,而 Serialize 和 Deserialize 调用不变。对于地点运用的演示,该格式化程序将转移以下结果。
威尼斯人线上娱乐 68

玖 、        连串化规则

鉴于类编写翻译后便无能为力连串化[类别化的时机是怎么着时候,由何人(CLEnclave依然其余)来兑现系列化?凡体系化的机遇是何许时候,由哪个人来达成?那么,webservice是什么时候类别化,哪一天反种类化?][类编译后便无能为力再种类化?是或不是类和对象都能够种类化?][类别化是否和原数据表单联系一点也不粗心?],所以在规划新类时应考虑种类化。

内需考虑的标题有:

1.      是或不是必须跨应用程序域来发送此类?

2.      是还是不是要远程应用此类?

3.      用户将如何运用此类?

只怕他们会从本身的类中派生出一个索要系列化的新类。只要有那种大概性,就应将类标志为可连串化。除下列情况以外,最好将全体类都标志为可系列化:

  • 拥有的类都永远也不会超越应用程序域。即使有些类不须要类别化但供给跨越应用程序域,请从
    MarshalByRefObject
    派生此类。
  • 类存款和储蓄仅适用于其日前实例的出格指针。例如,借使有个别类富含非受控的内部存款和储蓄器或文件句柄,请确定保证将那么些字段标记为
    NonSerialized
    或根本不类别化此类。
  • 有个别数据成员包括敏感新闻。在那种景观下,建议落实 ISerializable
    并仅系列化所必要的字段。

自个儿的难点:

1:本文中的存款和储蓄媒体是什么?xml?

2:种类化是对准对象的?那岂不是八个先后会须求过多的系列化?

3:什么是目的图表?

4:怎么样标记为Serializable?在类中,标记Serializable脾气?

5:为啥webservice类中绝非标准化记Serializable?

6:一般景况下,大家不需求用手写这一个体系化,反连串化代码吧?

7:共有多少种体系化?二进制类别化和xml连串化分别用在怎么地方?二进制/XML是还是不是正是本文所说的积存媒体?

8:不调用构造函数,会不会为编制程序带来影响,例如不能够在构造函数中添加逻辑?依旧,不必要关爱构造函数,因为对象的变量足以评释对象的情事?

9:反连串化不调用构造函数?者对品质会有多大影响,这么说调用构造函数并不是完全没有须要?

10:如果Serializable
属性不能够继承,为何webservice类中绝非设置Serializable 属性?

11:自定义连串化进程是何许,自身写代码系列化,反种类化对象?

12:反类别化的时候,无法调用构造函数吗?

13:对象被彻底重新构建,可是在反种类化进程中调用方法恐怕会带动不良的副效能,因为被调用的法子只怕引用了在调用时髦未反连串化的对象引用[不知道什么看头?是日前目的,照旧别的对象?]。

14:什么是散列表?

15:是还是不是种类化的目的中所引用的靶子都必须是可系列化的对象,不然无法反类别化。那么,是否webservice不可能引用未类别化的指标?

16:连串化对象中含有NonSerialized标记,是或不是有隐患?

17:连串化的时机是怎么时候,由哪个人(CLCR-V照旧此外)来兑现系列化?凡体系化的机遇是何等时候,由哪个人来达成?那么,webservice是何许时候种类化,曾几何时反类别化?

18:类编写翻译后便无能为力再种类化?是或不是类和目的都能够系列化?

19:系列化是或不是和原数据表单联系相当的细心?

<SOAP-ENV:Envelope
   xmlns:xsi=http://www.w3.org/2001/XMLSchema-instance
   xmlns:xsd="http://www.w3.org/2001/XMLSchema"
   xmlns:SOAP- ENC=http://schemas.xmlsoap.org/soap/encoding/
   xmlns:SOAP- ENV=http://schemas.xmlsoap.org/soap/envelope/
   SOAP-ENV:encodingStyle=
   "http://schemas.microsoft.com/soap/encoding/clr/1.0
  http://schemas.xmlsoap.org/soap/encoding/"
   xmlns:a1="http://schemas.microsoft.com/clr/assem/ToFile">

   <SOAP-ENV:Body>
     <a1:MyObject id="ref-1">
       <n1>1</n1>
       <n2>24</n2>
       <str id="ref-3">一些字符串</str>
     </a1:MyObject>
   </SOAP-ENV:Body>
</SOAP-ENV:Envelope>

 

威尼斯人线上娱乐 69亟需注意的是,不能继续 塞里alizable 属性。如若从 MyObject 派生出一个新的类,则这些新的类也亟须采用该属性进行标记,不然将不恐怕连串化。例如,要是打算连串化以下类实例,将会展现二个 塞里alizationException,表明 MyStuff 类型未标记为可连串化。
威尼斯人线上娱乐 70

public class MyStuff : MyObject
{
   public int n3;
}

威尼斯人线上娱乐 71利用类别化属性12分有利,可是它存在上述的片段限制。有关什么日期标记类以实行体系化(因为类编写翻译后就不可能再类别化),请参见有关表达(请参阅上边包车型大巴类别化规则)。
威尼斯人线上娱乐 72
威尼斯人线上娱乐 73接纳性系列化
威尼斯人线上娱乐 74类平时包罗不应被种类化的字段。例如,假诺有些类用贰个分子变量来存款和储蓄线程 ID。当此类被反连串化时,连串化此类时所蕴藏的 ID 对应的线程恐怕不再运转,所以对那么些值进行系列化没有意义。能够经过行使 NonSerialized 属性标记成员变量来防护它们被系列化,如下所示:
威尼斯人线上娱乐 75

[Serializable]
public class MyObject
{
   public int n1;
   [NonSerialized] public int n2;
   public String str;
}

威尼斯人线上娱乐 76自定义体系化
威尼斯人线上娱乐 77能够因而在对象上贯彻 ISerializable 接口来自定义系列化进程。这一功力在反体系化后成员变量的值失效时尤其有用,但是要求为变量提供值以重建对象的总体气象。要兑现 ISerializable,要求完毕 GetObjectData 方法以及多个特有的构造函数,在反体系化对象时要用到此构造函数。以下代码示例表明了如何在前一部分中提到的 MyObject 类上落实 I塞里alizable。
威尼斯人线上娱乐 78

[Serializable]
public class MyObject : ISerializable
{
   public int n1;
   public int n2;
   public String str;

   public MyObject()
   {
   }

   protected MyObject(SerializationInfo info, StreamingContext context)
   {
     n1 = info.GetInt32("i");
     n2 = info.GetInt32("j");
     str = info.GetString("k");
   }

   public virtual void GetObjectData(SerializationInfo info,
StreamingContext context)
   {
     info.AddValue("i", n1);
     info.AddValue("j", n2);
     info.AddValue("k", str);
   }
}

威尼斯人线上娱乐 79在体系化进程中调用 GetObjectData 时,须要填写方法调用中提供的 SerializationInfo 对象。只需按名称/值对的款式丰富将要种类化的变量。其名目能够是任何文件。只要已种类化的多寡能够在反种类化进程中平复对象,便足以自由采用添加至 SerializationInfo 的成员变量。假使基对象达成了 ISerializable,则派生类应调用其基对象的 GetObjectData 方法。
威尼斯人线上娱乐 80
威尼斯人线上娱乐 81亟待强调的是,将 ISerializable 添加至某些类时,须求同时达成 GetObjectData 以及相当的构造函数。借使缺少 GetObjectData,编译器将产生警告。不过,由于无法强制完毕构造函数,所以,贫乏构造函数时不会发出警告。假如在并未构造函数的境况下品尝反系列化有个别类,将会出现极度。在摒除潜在安全性和版本控制难题等方面,当前设计优化 SetObjectData 方法。例如,假设将 SetObjectData 方法定义为有个别接口的一有的,则此办法必须是公私艺术,那使得用户只可以编写代码来制止反复调用 SetObjectData 方法。可以想象,假设有个别对象正在举办有些操作,而某些恶意应用程序却调用此目的的 SetObjectData 方法,将会挑起部分潜在的难为。
威尼斯人线上娱乐 82
威尼斯人线上娱乐 83在反连串化进程中,使用出于此目标而提供的构造函数将 SerializationInfo 传递给类。对象反类别化时,对构造函数的其余可知性约束都将被忽略,由此,能够将类标志为 public、protected、internal 或 private。二个正确的方法是,在类未封装的情况下,将构造函数标记为 protect。假若类已打包,则应标记为 private。要上涨对象的情事,只需利用类别化时行使的称呼,从 SerializationInfo 中找找变量的值。要是基类完结了 ISerializable,则应调用基类的构造函数,以使基础对象能够还原其变量。
威尼斯人线上娱乐 84
威尼斯人线上娱乐 85借使从贯彻了 ISerializable 的类派生出2个新的类,则只要新的类中隐含别的索要系列化的变量,就必须同时达成构造函数以及 GetObjectData 方法。以下代码片段展现了怎么样运用上文所示的 MyObject 类来成功此操作。
威尼斯人线上娱乐 86

[Serializable]
public class ObjectTwo : MyObject
{
   public int num;

   public ObjectTwo() : base()
   {
   }

   protected ObjectTwo(SerializationInfo si, StreamingContext context) :
base(si,context)
   {
     num = si.GetInt32("num");
   }

   public override void GetObjectData(SerializationInfo si,
StreamingContext context)
   {
     base.GetObjectData(si,context);
     si.AddValue("num", num);
   }
}

威尼斯人线上娱乐 87纪事要在反连串化构造函数中调用基类,不然,将永远不会调用基类上的构造函数,并且在反类别化后也无力回天创设一体化的靶子。
威尼斯人线上娱乐 88
威尼斯人线上娱乐 89对象被彻底重新构建,可是在反连串化进程中调用方法恐怕会拉动不良的副效率,因为被调用的主意大概引用了在调用时未尝反种类化的靶子引用。要是正在开展反体系化的类达成了 IDeserializationCallback,则反类别化整个对象图表后,将自行调用 On塞里alization 方法。此时,引用的全体子对象均已通通复苏。有些类不使用上述事件侦听器,很难对它们进行反系列化,散列表正是1个拔尖的例子。在反体系化进程中找找关键字/值对格外不难,可是,由于不大概保障从散列表派生出的类已反连串化,所以把这一个目的添加回散列表时会见世有的难点。由此,建议如今不要在散列表上调用方法。
威尼斯人线上娱乐 90
威尼斯人线上娱乐 91类别化进程的手续
威尼斯人线上娱乐 92在格式化程序上调用 Serialize 方法时,对象体系化依照以下规则举行:
威尼斯人线上娱乐 93
威尼斯人线上娱乐 94检查格式化程序是或不是有代理接纳器。假诺有,检查代理选择器是不是处理钦命项目标靶子。借使选择器处理此目的类型,将在代理选用器上调用 I塞里alizable.GetObjectData。
威尼斯人线上娱乐 95如果没有代理采取器或有却不处理此类型,将检查是否采用 Serializable 属性对指标开展标记。假使未标记,将会吸引 SerializationException。
威尼斯人线上娱乐 96若果目的已被正确标记,将检核查象是不是完结了 ISerializable。借使已兑现,将在对象上调用 GetObjectData。
威尼斯人线上娱乐 97要是指标未落到实处 Serializable,将选用暗许的连串化策略,对负有未标记为 NonSerialized 的字段都进展类别化。
威尼斯人线上娱乐 98版本控制
威尼斯人线上娱乐 99.NET 框架支持版本控制和并排执行,并且,借使类的接口保持一致,全体类均可跨版本工作。由于系列化涉及的是成员变量而非接口,所以,在向要跨版本连串化的类中添加成员变量,或从中删除变量时,应严俊行事。特别是对于未达成 ISerializable 的类更应这么。若当前版本的意况发生了其他变更(例如添加成员变量、更改变量类型或改动变量名称),都代表假如一致档次的存活对象是接纳最初版本进行连串化的,则无从得逞对它们进行反系列化。
威尼斯人线上娱乐 100
威尼斯人线上娱乐 101只要目的的气象须求在区别版本间发生改变,类的撰稿人能够有二种选拔:
威尼斯人线上娱乐 102
威尼斯人线上娱乐 103福寿无疆 ISerializable。那使您能够确切地操纵种类化和反种类化进程,在反体系化进度中国科高校学地抬高和平化解说未来状态。
威尼斯人线上娱乐 104应用 NonSerialized 属性标记不主要的分子变量。仅当预测类在差别版本间的变通较小时,才可使用这一个选项。例如,把二个新变量添加至类的较高版本后,能够将该变量标记为 NonSerialized,以确定保障该类与早先时期版本保持万分。
威尼斯人线上娱乐 105体系化规则
威尼斯人线上娱乐 106由于类编写翻译后便不能系列化,所以在统一筹划新类时应考虑系列化。必要考虑的难点有:是还是不是必须跨应用程序域来发送此类?是不是要远程应用此类?用户将如何利用此类?可能他们会从作者的类中派生出二个内需系列化的新类。只要有那种大概性,就应将类标志为可系列化。除下列情状以外,最棒将全体类都标志为可类别化:
威尼斯人线上娱乐 107
威尼斯人线上娱乐 108负有的类都永远也不会超过应用程序域。若是某些类不供给连串化但须要跨越应用程序域,请从 马尔斯halByRefObject 派生此类。
威尼斯人线上娱乐 109类存款和储蓄仅适用于其近期实例的相当指针。例如,如若某些类富含非受控的内部存款和储蓄器或文件句柄,请确认保证将这么些字段标记为 NonSerialized 或根本不种类化此类。
威尼斯人线上娱乐 110或多或少数据成员包括敏感音信。在那种场地下,建议落实 ISerializable 并仅连串化所必要的字段。 


相关文章

发表评论

电子邮件地址不会被公开。 必填项已用*标注

网站地图xml地图