可以使用OnDeserializedAttribute而不是IDeserializationCallback接口吗?

时间:2010-10-26 12:29:44

标签: .net serialization ideserializationcallback

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

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在其他几个地方的构造函数之前被调用,所以我现在害怕它不是很可靠......

谢谢!

1 个答案:

答案 0 :(得分: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);
      }