首页 > 解决方案 > 为什么格式化程序是 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化,然后将反序列化的实例分配SecondTypeFirstType' 的字段。因为SecondTypeimplements IDeserializationCallback,所以SecondType直到它的OnDeserialization调用才被认为是“反序列化完成”。所以当SecondType完全反序列化时,它的num字段为0,然后这个SecondType实例被传递给FirstTypeFirstType调用它的时候OnDeserializationnumFromSecondType应该是0(因为secondType.num应该是0)。

但不是这样的,看起来是先调用FirstType'OnDeserialization方法,然后调用SecondType'OnDeserialization方法。但它不应该反过来SecondType吗- 的OnDeserialization方法应该首先调用,因为它必须先执行这个方法,然后才能被认为是完全“反序列化”的

那么格式化程序是否如此愚蠢以至于它不知道调用每个对象的OnDeserialization方法的正确顺序?

标签: c#.net

解决方案


那么格式化程序是否如此愚蠢以至于它不知道调用每个对象的OnDeserialization方法的正确顺序?

这不是愚蠢的问题。顺序是未定义的——这是因为在使用时很容易得到循环BinaryFormatter,所以所有可以保证的是,各种 IDeserializationCallback回调将在整个图形的常规反序列化代码之后发生——这里的意图是“父”样式对象可以应用与“子”数据相关的任何修正。如果父母和孩子都有 回调,那么:这听起来是个坏主意,但我想你可以在一个字段中跟踪“它完成了吗”(老实说,我不会 - 我只是从内部删除回调目的)。IDeserializationCallback


推荐阅读