NET中对象序列化方法毕业论文(2)

2013-04-29 01:14
导读:如果要求具有可移植性,应该使用 SoapFormatter。所要做的更改只是将以上代码中的格式化程序换成 SoapFormatter,而 Serialize 和 Deserialize 调用不变。对于上面
     如果要求具有可移植性,应该使用 SoapFormatter。所要做的更改只是将以上代码中的格式化程序换成 SoapFormatter,而 Serialize 和 Deserialize 调用不变。对于上面使用的示例,该格式化程序将生成以下结果。<SOAP-ENV:Envelopexmlns: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>需要注意的是,无法继承 Serializable 属性。如果从 MyObject 派生出一个新的类,则这个新的类也必须使用该属性进行标记,否则将无法序列化。例如,如果试图序列化以下类实例,将会显示一个 SerializationException,说明 MyStuff 类型未标记为可序列化。public class MyStuff:MyObject {  public int n3;}5  选择性序列化     类通常包含不应被序列化的字段。例如,假设某个类用一个成员变量来存储线程 ID。当此类被反序列化时,序列化此类时所存储的 ID 对应的线程可能不再运行,所以对这个值进行序列化没有意义。可以通过使用 NonSerialized 属性标记成员变量来防止它们被序列化,如下所示:[Serializable]public class MyObject {public int n1;[NonSerialized]public int n2;public String str;}6  自定义序列化     可以通过在对象上实现 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,编译器将发出警告。但是,由于无法强制实现构造函数,所以,缺少构造函数时不会发出警告。如果在没有构造函数的情况下尝试反序列化某个类,将会出现异常。     在反序列化过程中,使用出于此目的而提供的构造函数将 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);  }}切记要在反序列化构造函数中调用基类,否则,将永远不会调用基类上的构造函数,并且在反序列化后也无法构建完整的对象。7  序列化过程的规则     在格式化程序上调用 Serialize 方法时,对象序列化按照以下规则进行:检查格式化程序是否有代理选取器。如果有,检查代理选取器是否处理指定类型的对象。如果选取器处理此对象类型,将在代理选取器上调用 ISerializable.GetObjectData。      如果没有代理选取器或有却不处理此类型,将检查是否使用 Serializable 属性对对象进行标记。如果未标记,将会引发 SerializationException。 如果对象已被正确标记,将检查对象是否实现了 ISerializable。如果已实现,将在对象上调用 GetObjectData。
上一篇:基于构造超平面的两阶段决策树算法的研究 下一篇:没有了