ISerializable的和向后兼容性
-
26-09-2019 - |
题
我必须工作所使用的BinaryFormatter序列化应用数据转换成一个文件流的旧的应用程序(在一个文件名为“data.oldformat”说) 没有任何optimizazion主类已被标记与属性
<serializable()>public MainClass
.......
end class
和序列化代码
dim b as new binaryformatter
b.serialize(mystream,mymainclass)
在试图优化序列化/反序列化过程简单地我提出的类实现ISerializable接口和写了一些优化序列化例程
<serializable()>public MainClass
implements ISerializable
.......
end class
在优化的作品真的很好,但我必须找到一个方法来reatrive旧文件中的数据的后向兼容性。
如何做到这一点??
皮耶路易吉
解决方案
<强> stmax 强>具有优异的答案,但是我将实施像这样,它使用SerializationEntry.GetEnumerator()
代替try/catch
。这种方式是清洁器和显著更快。
public MainClass(SerializationInfo info, StreamingContext context) {
int version = 0;
foreach (SerializationEntry s in info)
{
if (s.Name == "version")
{
version = (int)s.Value;
break;
}
}
switch (version) {
case 0:
// deserialize "old format"
break;
case 1:
// deserialize "new format, version 1"
break;
default:
throw new NotSupportedException("version " + version + " is not supported.");
}
}
我宁愿使用.FirstOrDefault()LINQ的版本,但SerializationInfo中不实现IEnumerable - 在脸上,古怪的是,它甚至没有实现旧IEnumerable接口
其他提示
既然你已经实现ISerializable接口,你可能也已经添加了必需的构造函数:
public MainClass(SerializationInfo info, StreamingContext context) {}
您可以使用传递给构造函数的信息对象从序列化的文件检索数据。 按缺省(即,当没有ISerializable的实施),字段名称用作序列化过程中的标识符。所以如果你的老班有场“INT X”,你可以反序列化这一点使用:
this.x = info.GetInt32("x");
有关新版本我通常序列化过程中添加一个“版本”项,是这样的:
public void GetObjectData(SerializationInfo info, StreamingContext context) {
info.AddValue("version", 1);
info.AddValue("othervalues", ...);
}
在反序列化过程中,您可以检查此版本的条目,并据此反序列化:
public MainClass(SerializationInfo info, StreamingContext context) {
int version;
try {
version = info.GetInt32("version");
}
catch {
version = 0;
}
switch (version) {
case 0:
// deserialize "old format"
break;
case 1:
// deserialize "new format, version 1"
break;
default:
throw new NotSupportedException("version " + version + " is not supported.");
}
}
我还没有编译的代码,可能包含输入错误。
希望帮助。
刚刚尝试同样的事情,你到目前为止一直在做的。
BinaryFormatter b = new BinaryFormatter();
MainClass a = b.DeSerialize(mystream) as MainClass;
实施了ISerializable并没有改变原来的类,基本上你刚刚增加了一些方法
当您的序列化对象添加一个额外的版本场(这应该不会增加太多的开销)。然后在您的GetObjectData方法,尝试检索版本字段第一,在此基础上是否存在(被捕捉SerializationException)反序列化老办法还是新途径。旧的方式将刚刚序列化的所有数据,所以你应该只能够调用get ...所有字段。
您以前的代码应该工作。你会得到一个异常? 尝试使用新的构造:
Protected Sub New(ByVal info As SerializationInfo, ByVal context As StreamingContext)