c# - 为什么格式化程序是 BinaryFormatter 它无法正确处理 IDeserializationCallback
问题描述
假设我们有以下代码:
static void Main(string[] args) {
var firstType = new FirstType(new SecondType(2021));
var stream = new MemoryStream();
BinaryFormatter formatter = new BinaryFormatter();
formatter.Serialize(stream, firstType);
stream.Position = 0;
var firstTypeReturned = (FirstType)formatter.Deserialize(stream);
Console.WriteLine(firstTypeReturned.numFromSecondType);
}
[Serializable]
class FirstType : IDeserializationCallback {
public SecondType secondType;
public int numFromSecondType = -1;
public FirstType(SecondType t) {
secondType = t;
}
void IDeserializationCallback.OnDeserialization(Object sender) {
numFromSecondType = secondType.num;
}
}
[Serializable]
class SecondType : IDeserializationCallback {
public int num;
public SecondType(int num) {
this.num = num;
}
void IDeserializationCallback.OnDeserialization(Object sender) {
num = 0;
}
}
输出是 2021。
我希望输出为 0,因为从我的角度来看,FirstType
它包含一个SecondType
对象字段,因此为了成功反序列化FirstType
实例,您必须先反序列SecondType
化,然后将反序列化的实例分配SecondType
给 FirstType
' 的字段。因为SecondType
implements IDeserializationCallback
,所以SecondType
直到它的OnDeserialization
调用才被认为是“反序列化完成”。所以当SecondType
完全反序列化时,它的num
字段为0,然后这个SecondType
实例被传递给FirstType
,FirstType
调用它的时候OnDeserialization
,numFromSecondType
应该是0(因为secondType.num
应该是0)。
但不是这样的,看起来是先调用FirstType
'OnDeserialization
方法,然后调用SecondType
'OnDeserialization
方法。但它不应该反过来SecondType
吗- 的OnDeserialization
方法应该首先调用,因为它必须先执行这个方法,然后才能被认为是完全“反序列化”的
那么格式化程序是否如此愚蠢以至于它不知道调用每个对象的OnDeserialization
方法的正确顺序?
解决方案
那么格式化程序是否如此愚蠢以至于它不知道调用每个对象的
OnDeserialization
方法的正确顺序?
这不是愚蠢的问题。顺序是未定义的——这是因为在使用时很容易得到循环BinaryFormatter
,所以所有可以保证的是,各种 IDeserializationCallback
回调将在整个图形的常规反序列化代码之后发生——这里的意图是“父”样式对象可以应用与“子”数据相关的任何修正。如果父母和孩子都有 回调,那么:这听起来是个坏主意,但我想你可以在一个字段中跟踪“它完成了吗”(老实说,我不会 - 我只是从内部删除回调目的)。IDeserializationCallback