可以OnDeserializedAttribute用来代替IDeserializationCallback界面? [英] Can OnDeserializedAttribute be used instead of IDeserializationCallback interface?

查看:158
本文介绍了可以OnDeserializedAttribute用来代替IDeserializationCallback界面?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

由于MSDN指出<一href="http://msdn.microsoft.com/en-us/library/system.runtime.serialization.ondeserializedattribute.aspx"相对=nofollow>此处,就可以了。 不过,我已经花了2小时挖的mscorlib code,因为在某些情况下,BinaryFormatter的叫我的方法打上OnDeserialized前反序列化的构造。也就是说,顺序为:

As MSDN states here, it can. But I've spent 2 hours digging mscorlib code, because in some cases the BinaryFormatter called my method marked with OnDeserialized BEFORE deserialization constructor. That is, the order was

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

虽然我希望它是

While I was expecting it to be

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

和终点。当我实现IDeserializationCallback接口,其方法OnDeserialization调用构造函数之后,因为我想和预期。

And the final point. When I implemented IDeserializationCallback interface, its method OnDeserialization was called AFTER constructor, as I wanted and expected.

我试图重现这对一些简单的阶级结构,但一切正常。 在我们的项目图被序列化的对象是非常复杂的,所以我不知道在哪里挖。检查的mscorlib程序code与反射器并没有有很大的帮助 - 反序列化code是太复杂,我找出其中的问题来自

I tried to reproduce this on some simple class structure, but there everything worked fine. In our project the objects graph being serialized is very complex, so I do not know where to dig. Inspecting the mscorlib code with reflector did not help a lot - the deserialization code is too complicated for me to figure out where the problem comes from.

所以,没有任何人知道什么可能会导致这样的问题?我们使用的假定OnDeserialized调用之前在其他几个地方的构造,所以我很害怕现在,它是不是很可靠的......

So, does anybody know what could be causing such problem? We use the assumption that OnDeserialized is called BEFORE the constructor in several other places so I am scared now that it is not very reliable...

谢谢!

推荐答案

最后,我找到了答案,以我自己的问题,如果有人有兴趣。 考虑这篇文章的结尾的例子。有两种类,实例,其中包含相互之间的引用。在这种条件下,没有可能性,即这两个实例的反串行化的构造被传递与构造的对象。所以串行首先调用构造函数传递给它第二个类型的unconstructed实例之一,然后调用该对象的构造器,通过它构建了第一类的实例。在这样一种方式,它可以帮助我们还原物体的连接,所以它真的是最好的,可以做的!

Finally, I have the answer to my own question, if anyone would be interested. Consider the example in the end of this post. There are two classes, instances of which contain references to each other. Under such conditions there is no possibility that deserializing constructors of both instances are passed with constructed objects. So serializer first calls one of constructors passing it an unconstructed instance of second type and then calls constructor of that object, passing it constructed instance of first type. In such a way it helps us to restore objects connections, so it is really the best it can do!

其次, OnDeserializing OnDeserialized 在这种情况下,回调可以被称为我指出了问题,而 OnDeserialization IDeserializationCallback 的方法总是叫完整的对象图形已经反序列化之后,正是因为其在规范中规定。

Next, OnDeserializing and OnDeserialized callbacks in such cases may be called as I pointed in the question, while OnDeserialization method of IDeserializationCallback is always called after the COMPLETE objects graph has been deserialized, exactly as it is stated in its specification.

保持所有上述想法,我觉得最好的方法是使用 IDeserializationCallback 界面做任何我需要的后反序列化处理。在这种情况下,我相信构造函数的调用的所有对象,我可以在一个安全的方式做必要的修改。

Keeping all the above in mind, I find it the best to use IDeserializationCallback interface to do any post-deserialization processing I need. In that case I am sure that constructors are called for all objects and I can do necessary modifications in a 'safe' way.

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

这篇关于可以OnDeserializedAttribute用来代替IDeserializationCallback界面?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆