做百度推广是不是得有个网站先,道滘仿做网站,推广方案应该有哪些方面,10套免费ppt模板序列化是指将对象实例的状态存储到存储媒体的过程。在此过程中#xff0c;先将对象的公共字段和私有字段以及类的名称#xff08;包括类所在的程序集#xff09;转换为字节流#xff0c;然后再把字节流写入数据流。在随后对对象进行反序列化时#xff0c;将创建出与原对象…序列化是指将对象实例的状态存储到存储媒体的过程。在此过程中先将对象的公共字段和私有字段以及类的名称包括类所在的程序集转换为字节流然后再把字节流写入数据流。在随后对对象进行反序列化时将创建出与原对象完全相同的副本。在面向对象的环境中实现序列化机制时必须在易用性和灵活性之间进行一些权衡。只要您对此过程有足够的控制能力就可以使该过程在很大程度上自动进行。例如简单的二进制序列化不能满足需要或者由于特定原因需要确定类中那些字段需要序列化。以下各部分将探讨 .NET 框架提供的可靠的序列化机制并着重介绍使您可以根据需要自定义序列化过程的一些重要功能。持久存储我们经常需要将对象的字段值保存到磁盘中并在以后检索此数据。尽管不使用序列化也能完成这项工作但这种方法通常很繁琐而且容易出错并且在需要跟踪对象的层次结构时会变得越来越复杂。可以想象一下编写包含大量对象的大型业务应用程序的情形程序员不得不为每一个对象编写代码以便将字段和属性保存至磁盘以及从磁盘还原这些字段和属性。序列化提供了轻松实现这个目标的快捷方法。公共语言运行时 (CLR) 管理对象在内存中的分布.NET 框架则通过使用反射提供自动的序列化机制。对象序列化后类的名称、程序集以及类实例的所有数据成员均被写入存储媒体中。对象通常用成员变量来存储对其他实例的引用。类序列化后序列化引擎将跟踪所有已序列化的引用对象以确保同一对象不被序列化多次。.NET 框架所提供的序列化体系结构可以自动正确处理对象图表和循环引用。对对象图表的唯一要求是由正在进行序列化的对象所引用的所有对象都必须标记为 Reftag-863-1.htmlSerializable请参阅基本序列化。否则当序列化程序试图序列化未标记的对象时将会出现异常。当反序列化已序列化的类时将重新创建该类并自动还原所有数据成员的值。按值封送对 象仅在创建对象的应用程序域中有效。除非对象是从 MarshalByRefObject 派生得到或标记为 Serializable否则任何将对象作为参数传递或将其作为结果返回的尝试都将失败。如果对象标记为 Serializable则该对象将被自动序列化并从一个应用程序域传输至另一个应用程序域然后进行反序列化从而在第二个应用程序域中产生出该对象的一个精确副本。此过程通常称为按值封送。如果对象是从 MarshalByRefObject 派生得到则从一个应用程序域传递至另一个应用程序域的是对象引用而不是对象本身。也可以将从 MarshalByRefObject 派生得到的对象标记为 Serializable。远程使用此对象时负责进行序列化并已预先配置为 SurrogateSelector 的格式化程序将控制序列化过程并用一个代理替换所有从 MarshalByRefObject 派生得到的对象。如果没有预先配置为 SurrogateSelector序列化体系结构将遵从下面的标准序列化规则请参阅序列化过程的步骤。基本序列化要使一个类可序列化最简单的方法是使用 Serializable 属性对它进行标记如下所示using System.Runtime.Serialization;using System.Runtime.Serialization.Formatters.Binary;[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();本例使用二进制格式化程序进行序列化。您只需创建一个要使用的流和格式化程序的实例然后调用格式化程序的 Serialize 方法。流和要序列化的对象实例作为参数提供给此调用。类中的所有成员变量甚至标记为 private 的变量都将被序列化但这一点在本例中未明确体现出来。在这一点上二进制序列化不同于只序列化公共字段的 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 平台上进行反序列化的对象此格式化程序无疑是一个理想工具。需要注意的是对对象进行反序列化时并不调用构造函数。对反序列化添加这项约束是出于性能方面的考虑。但是这违反了对象编写者通常采用的一些运行时约定因此开发人员在将对象标记为可序列化时应确保考虑了这一特殊约定。如果要求具有可移植性请使用 SoapFormatter。所要做的更改只是将以上代码中的格式化程序换成 SoapFormatter而 Serialize 和 Deserialize 调用不变。对于上面使用的示例该格式化程序将生成以下结果。SOAP-ENV:Envelopexmlns:xsihttp://www.w3.org/2001/XMLSchema-instancexmlns:xsdhttp://www.w3.org/2001/XMLSchemaxmlns:SOAP- ENChttp://schemas.xmlsoap.org/soap/encoding/xmlns:SOAP- ENVhttp://schemas.xmlsoap.org/soap/envelope/SOAP-ENV:encodingStylehttp://schemas.microsoft.com/soap/encoding/clr/1.0http://schemas.xmlsoap.org/soap/encoding/xmlns:a1http://schemas.microsoft.com/clr/assem/ToFileSOAP-ENV:Bodya1:MyObject idref-1n11/n1n224/n2str idref-3一些字符串/str/a1:MyObject/SOAP-ENV:Body/SOAP-ENV:Envelope需 要注意的是无法继承 Serializable 属性。如果从 MyObject 派生出一个新的类则这个新的类也必须使用该属性进行标记否则将无法序列化。例如如果试图序列化以下类实例将会显示一个 SerializationException说明 MyStuff 类型未标记为可序列化。public class MyStuff : MyObject{public int n3;}使用序列化属性非常方便但是它存在上述的一些限制。有关何时标记类以进行序列化因为类编译后就无法再序列化请参考有关说明请参阅下面的序列化规则。选择性序列化类通常包含不应被序列化的字段。例如假设某个类用一个成员变量来存储线程 ID。当此类被反序列化时序列化此类时所存储的 ID 对应的线程可能不再运行所以对这个值进行序列化没有意义。可以通过使用 NonSerialized 属性标记成员变量来防止它们被序列化如下所示[Serializable]public class MyObject{public int n1;[NonSerialized] public int n2;public String str;}自定义序列化可 以通过在对象上实现 ISerializable 接口来自定义序列化过 搞笑的qq表情 程。这一功能在反序列化后成员变量的值失效时尤其有用但是需要为变量提供值以重建对象的完整状态。要实现 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。一个不错的办法是在类未封装的情况下将构造函数标记为 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);}}切记要在反序列化构造函数中调用基类否则将永远不会调用基类上的构造函数并且在反序列化后也无法构建完整的对象。对象被彻底重新构建但是在反系列化过程中调用方法可能会带来不良的副作用,因为被调用的方法可能引用了在调用时尚未反序列化的对象引用。如果正在进行反序列化的类实现了 IDeserializationCallback则反序列化整个对象图表后将自动调用 OnSerialization 方法。此时引用的所有子对象均已完全还原。有些类不使用上述事件侦听器很难对它们进行反序列化散列表便是一个典型的例子。在反序列化过程中检索关键字/值对非常容易但是由于无法保证从散列表派生出的类已反序列化所以把这些对象添加回散列表时会出现一些问题。因此建议目前不要在散列表上调用方法。序列化过程的步骤在格式化程序上调用 Serialize 方法时对象序列化按照以下规则进行检查格式化程序是否有代理选取器。如果有检查代理选取器是否处理指定类型的对象。如果选取器处理此对象类型将在代理选取器上调用 ISerializable.GetObjectData。如果没有代理选取器或有却不处理此类型将检查是否使用 Serializable 属性对对象进行标记。如果未标记将会引发 SerializationException。如果对象已被正确标记将检查对象是否实现了 ISerializable。如果已实现将在对象上调用 GetObjectData。如果对象未实现 Serializable将使用默认的序列化策略对所有未标记为 NonSerialized 的字段都进行序列化。版本控制.NET 框架支持版本控制和并排执行并且如果类的接口保持一致所有类均可跨版本工作。由于序列化涉及的是成员变量而非接口所以在向要跨版本序列化的类中添加成员变量或从中删除变量时应谨慎行事。特别是对于未实现 ISerializable 的类更应如此。若当前版本的状态发生了任何变化例如添加成员变量、更改变量类型或更改变量名称都意味着如果同一类型的现有对象是使用早期版本进行序列化的则无法成功对它们进行反序列化。如果对象的状态需要在不同版本间发生改变类的作者可以有两种选择实现 ISerializable。这使您可以精确地控制序列化和反序列化过程在反序列化过程中正确地添加和解释未来状态。使用 NonSerialized 属性标记不重要的成员变量。仅当预计类在不同版本间的变化较小时才可使用这个选项。例如把一个新变量添加至类的较高版本后可以将该变量标记为 NonSerialized以确保该类与早期版本保持兼容。序列化规则由于类编译后便无法序列化所以在设计新类时应考虑序列化。需要考虑的问题有是否必须跨应用程序域来发送此类是否要远程使用此类用户将如何使用此类也许他们会从我的类中派生出一个需要序列化的新类。只要有这种可能性就应将类标记为可序列化。除下列情况以外最好将所有类都标记为可序列化所有的类都永远也不会跨越应用程序域。如果某个类不要求序列化但需要跨越应用程序域请从 MarshalByRefObject 派生此类。类存储仅适用于其当前实例的特殊指针。例如如果某个类包含非受控的内存或文件句柄请确保将这些字段标记为 NonSerialized 或根本不序列化此类。某些数据成员包含敏感信息。在这种情况下建议实现 ISerializable 并仅序列化所要求的字段转载于:https://www.cnblogs.com/liuzhiwei/archive/2012/10/19/2731014.html