我有一个客户端和一个服务器应用程序,它们使用二进制序列化通过 .NET 2.0 Remoting 进行通信。
对数据传输对象的接口和实现类之一进行了小的更改,添加了一个字符串数组字段。
如果我重新部署新版本的服务器应用程序,我的旧客户端会继续工作吗?
我认为他们会,因为没有从接口和直接实现中删除任何内容,但我不确定。
它可能归结为另一个问题 - 二进制反序列化器是否“足够聪明”通过将无法在输入二进制流中找到数据的字段初始化为 null 来处理这种情况,或者它会中断并抛出异常?
我有一个客户端和一个服务器应用程序,它们使用二进制序列化通过 .NET 2.0 Remoting 进行通信。
对数据传输对象的接口和实现类之一进行了小的更改,添加了一个字符串数组字段。
如果我重新部署新版本的服务器应用程序,我的旧客户端会继续工作吗?
我认为他们会,因为没有从接口和直接实现中删除任何内容,但我不确定。
它可能归结为另一个问题 - 二进制反序列化器是否“足够聪明”通过将无法在输入二进制流中找到数据的字段初始化为 null 来处理这种情况,或者它会中断并抛出异常?
您可以将属性添加到新属性:OptionalField
. 如果没有该属性,反序列化器将无法将序列化数据转换回更新后的定义。该属性是为了确保反序列化器可以优雅地处理“丢失”的数据。
If you want to set a default value for the new property, in the case that no appropriate data for it is deserialized, implement the IDeserializationCallback
interface, and set the default value, if any, in the resulting method.
它很可能会引发异常,您始终可以通过继承来实现自己的序列化器,ISerializable
并使用您自己的方法实现版本控制GetObjectData
......这将使您对要序列化的数据有更严格的控制。 ..这是一个例子
using System.Runtime.Serialization;
using System.Runtime.Serialization.Formatters.Binary;
public class MyFooBar : ISerializable{
private float _fVersion = 1.0;
public MyFooBar(SerializationInfo info, StreamingContext context) {
this._fVersion = info.GetSingle("FooBarVersionID");
if (this._fVersion == 1.0F) bOk = this.HandleVersionOnePtZero(info, context);
if (!bOk) throw new SerializationException(string.Format("MyFooBar: Could not handle this version {0}.", this._fVersion.ToString()));
}
[System.Security.Permissions.SecurityPermission(System.Security.Permissions.SecurityAction.LinkDemand, Flags = System.Security.Permissions.SecurityPermissionFlag.SerializationFormatter)]
public void GetObjectData(SerializationInfo info, StreamingContext context) {
info.AddValue("FooBarVersionID", this._fVersion);
if (this._fVersion == 1.0F) {
// Bool's...
info.AddValue("FooBarBool", FooBarBool);
// etc... for Version 1.0
}
if (this._fVersion == 1.1F){
// etc... for Version 1.0
}
}
}
并在序列化/反序列化时在此上下文中使用 MyFooBar,如下所示
public bool Deserialize(string sFileName) {
bool bSuccessful = false;
//
if (!System.IO.File.Exists(sFileName)) return false;
fuBar = new MyFooBar();
//
try {
using (FileStream fStream = new FileStream(sFileName, FileMode.Open)) {
try {
BinaryFormatter bf = new BinaryFormatter();
fuBar = (MyFooBar)bf.Deserialize(fStream);
bSuccessful = true;
} catch (System.Runtime.Serialization.SerializationException sEx) {
System.Diagnostics.Debug.WriteLine(string.Format("SERIALIZATION EXCEPTION> DETAILS ARE {0}", sEx.ToString()));
bSuccessful = false;
}
}
} catch (System.IO.IOException ioEx) {
System.Diagnostics.Debug.WriteLine(string.Format("IO EXCEPTION> DETAILS ARE {0}", ioEx.ToString()));
bSuccessful = false;
}
return (bSuccessful == true);
}
在 2.0+ 版本中有更简洁的方法可以做到这一点,但我更喜欢这种方式。