7

正如 MSDN在这里所说,它可以。但是我花了 2 个小时来挖掘 mscorlib 代码,因为在某些情况下,BinaryFormatter 调用了我在反序列化构造函数之前标记为 OnDeserialized 的方法。也就是说,订单是

OnDeserializing(StreamingContext context)
OnDeserialized(StreamingContext context)
.ctor(SerializationInfo info, StreamingContext context)

虽然我期待它是

OnDeserializing(StreamingContext context)
.ctor(SerializationInfo info, StreamingContext context)
OnDeserialized(StreamingContext context)

最后一点。当我实现 IDeserializationCallback 接口时,它的方法 OnDeserialization 被称为 AFTER 构造函数,正如我想要和预期的那样。

我试图在一些简单的类结构上重现这一点,但一切正常。在我们的项目中,被序列化的对象图非常复杂,所以我不知道在哪里挖掘。用反射器检查 mscorlib 代码并没有多大帮助——反序列化​​代码太复杂了,我无法弄清楚问题出在哪里。

那么,有人知道是什么导致了这样的问题吗?我们假设 OnDeserialized 在其他几个地方的构造函数之前被调用,所以我现在很害怕它不是很可靠......

谢谢!

4

1 回答 1

6

最后,我有我自己问题的答案,如果有人感兴趣的话。考虑本文末尾的示例。有两个类,它们的实例包含对彼此的引用。在这种情况下,两个实例的反序列化构造函数不可能与构造对象一起传递。因此,序列化程序首先调用其中一个构造函数,传递给它一个未构造的第二种类型的实例,然后调用该对象的构造函数,传递给它构造的第一种类型的实例。通过这种方式,它可以帮助我们恢复对象连接,所以它确实是它所能做的最好的!

接下来,OnDeserializingOnDeserialized这种情况下可以调用回调,正如我在问题中指出的那样,而OnDeserialization方法IDeserializationCallback总是在 COMPLETE 对象图被反序列化后调用,正如其规范中所述。

牢记以上所有内容,我发现最好使用IDeserializationCallback接口来执行我需要的任何后反序列化处理。在这种情况下,我确信所有对象都会调用构造函数,并且我可以以“安全”的方式进行必要的修改。

      [Serializable]
      class One :ISerializable, IDeserializationCallback
      {
           public Two m_two;
           public One() {}
           public One(SerializationInfo info, StreamingContext context)
           {
                var two = (Two)info.GetValue("m_two", typeof(Two));
                m_two = two;
           }
           public void GetObjectData(SerializationInfo info, StreamingContext context)
           {
                info.AddValue("m_two", m_two);
           }
           private bool m_onDeserializing;
           private bool m_onDeserialized;
           private bool m_callback;
           public void OnDeserialization(object sender)
           {
                m_callback = true;
           }
           [OnDeserializing]
           void OnDeserializing(StreamingContext context)
           {
                m_onDeserializing = true;
           }

           [OnDeserialized]
           void OnDeserialized(StreamingContext context)
           {
                m_onDeserialized = true;
           }
      }

      [Serializable]
      private class Two : ISerializable, IDeserializationCallback
      {
           public Two(){}
           public One m_one;
           public Two(SerializationInfo info, StreamingContext context)
           {
                var one = (One)info.GetValue("m_one", typeof(One));
                m_one = one;
           }
           public void GetObjectData(SerializationInfo info, StreamingContext context)
           {
                info.AddValue("m_one", m_one);
           }
           private bool m_onDeserializing;
           private bool m_onDeserialized;
           private bool m_callback;
           public void OnDeserialization(object sender)
           {
                m_callback = true;
           }
           [OnDeserializing]
           void OnDeserializing(StreamingContext context)
           {
                m_onDeserializing = true;
           }
           [OnDeserialized]
           void OnDeserialized(StreamingContext context)
           {
                m_onDeserialized = true;
           }
      }

      [STAThread]
      static void Main()
      {
           var one = new One();
           one.m_two = new Two();
           one.m_two.m_one = one;

           BinaryFormatter formatter = new BinaryFormatter();
           MemoryStream mss =new MemoryStream();
           formatter.Serialize(mss, one);
           mss.Position = 0;
           var deserialize = formatter.Deserialize(mss);
      }
于 2012-01-16T11:28:52.620 回答