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

iro*_*nic 7 .net serialization ideserializationcallback

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

OnDeserializing(StreamingContext context)
OnDeserialized(StreamingContext context)
.ctor(SerializationInfo info, StreamingContext context)
Run Code Online (Sandbox Code Playgroud)

虽然我期待它

OnDeserializing(StreamingContext context)
.ctor(SerializationInfo info, StreamingContext context)
OnDeserialized(StreamingContext context)
Run Code Online (Sandbox Code Playgroud)

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

我尝试在一些简单的类结构上重现这一点,但一切都运行正常.在我们的项目中,被序列化的对象图非常复杂,所以我不知道在哪里挖掘.使用反射器检查mscorlib代码并没有太大帮助 - 反序列化代码对我来说太复杂了,无法找出问题的来源.

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

谢谢!

iro*_*nic 6

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

接下来,OnDeserializing以及OnDeserialized在这种情况下,回调可以被称为我的问题指出,虽然OnDeserialization方法IDeserializationCallback的完整图形对象后,总是叫反序列化,正是因为它在它的规格说明.

记住以上所有内容,我发现最好使用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);
      }
Run Code Online (Sandbox Code Playgroud)