.net - 可以使用 OnDeserializedAttribute 代替 IDeserializationCallback 接口(interface)吗?

标签 .net serialization ideserializationcallback

正如 MSDN 所说 here , 它可以。 但我花了 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 接口(interface)时,它的方法 OnDeserialization 在构造函数之后被调用,正如我想要和预期的那样。

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

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

谢谢!

最佳答案

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

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

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

      [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);
      }

关于.net - 可以使用 OnDeserializedAttribute 代替 IDeserializationCallback 接口(interface)吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4023644/

相关文章:

java - 如何将带有数组字段的 JSON 序列化为带有字符串字段的对象?

c# - Hashtable.OnDeserialization

c# - .NET 7 中的 Azure Functions(独立)发布到 Azure,加载了 0 个函数

c# - BinaryFormatter 是否应用任何压缩?

c# - 是否可以从 C++ 应用程序调用 C# 应用程序?

vb.net - Newsoft JSON .NET 反序列化为 VB.net 中具有私有(private)属性的对象

java - 无法使用 GSON 将复杂的 json 序列化为对象?

c# - IDeserializationCallback 与 OnDeserializedAttribute

c# - Kendo Combobox 未触发所需的验证消息