我有一个使用 BinaryFormatter
序列化数据的应用程序。一个成员被添加到从一个版本序列化到下一个版本的类中,而不更改类名。添加了代码以处理旧序列化文件中可能缺少添加成员的情况:
private void readData(FileStream fs, SymmetricAlgorithm dataKey)
{
CryptoStream cs = null;
try
{
cs = new CryptoStream(fs, dataKey.CreateDecryptor(),
CryptoStreamMode.Read);
BinaryFormatter bf = new BinaryFormatter();
string string1 = (string)bf.Deserialize(cs);
// do stuff with string1
bool bool1 = (bool)bf.Deserialize(cs);
// do stuff with bool1
ushort ushort1 = (ushort)bf.Deserialize(cs);
// do stuff with ushort1
// etc. etc. ...
// this field was added later, so it may not be present
// in the serialized binary data. Check for it, and if
// it's not there, do some default behavior
NewStuffIncludedRecently newStuff = null;
try
{
newStuff = (NewStuffIncludedRecently)bf.Deserialize(cs);
}
catch
{
newStuff = null;
}
_newStuff = newStuff != null ?
new NewStuffIncludedRecently(newStuff) :
new NewStuffIncludedRecently();
}
catch (Exception e)
{
// ...
}
finally
{
// ...
}
}
我现在的意思是,我真的很想冲洗并重复我想添加的另一个成员,这意味着我要添加另一个字段和 try-catch block ,类似于NewStuffIncludedRecently
。
我曾想过让整个类都[Serializable]
,但这不会破坏与旧序列化数据的兼容性吗?
我主要担心的是我不清楚反序列化是如何工作的。如果我像上面一样添加另一个可选字段的处理,它会起作用吗?我还有哪些其他选择可以更好地处理这些变化?
一如既往地提前致谢。
最佳答案
如果您使用 [OptionalField]
标记新字段,它应该 可以工作,但我听说在某些情况下会出现问题。我不能肯定地说,因为我避免使用 BinaryFormatter,因为它在版本控制时有很多问题 :)(另外,它不像某些替代方案那样“紧凑”,如果你想跨平台的话会有严重的问题, 或者到 CF/SL 等)
如果您正在实现 ISerializable
,您可以尝试:
foreach(SerializationEntry entry in info) {
switch(entry.Name) {
case "Name": Name = (string)info.Value;
case "Id": Id = (int)info.Value;
...
}
}
但是,必须再次强调 - 这是做事的艰难方式 :p 使用这种方法,您只需处理实际存在的数据。
关于c# - BinaryFormatter 中可选字段的反序列化,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8245501/