Peut OnDeserializedAttribute être utilisé à la place de l'interface IDeserializationCallback?

StackOverflow https://stackoverflow.com/questions/4023644

Question

MSDN indique , il pouvez. Mais j'ai passé 2 heures creuser code mscorlib, car dans certains cas BinaryFormatter appelé ma méthode marquée avec AVANT constructeur désérialisation OnDeserialized. C'est, l'ordre était

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

Alors que je m'y attendais pas à être

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

Et le dernier point. Quand je l'interface IDeserializationCallback mis en œuvre, sa méthode OnDeserialization fut appelé constructeur, comme je voulais et attendais.

J'ai essayé de reproduire cela sur une structure de classe simple, mais tout a bien fonctionné. Dans notre projet, les objets graphique en cours de sérialisation est très complexe, donc je ne sais pas où creuser. Inspectant le code mscorlib avec réflecteur n'a pas aidé beaucoup -. Le code désérialisation me est trop compliqué pour savoir où le problème vient de

Alors, est-ce que quelqu'un sait ce qui pourrait causer ce problème? Nous utilisons l'hypothèse que OnDeserialized est appelée avant que le constructeur dans plusieurs autres endroits, donc je suis peur maintenant que ce n'est pas très fiable ...

Merci!

Était-ce utile?

La solution

Enfin, j'ai la réponse à ma propre question, si quelqu'un serait intéressé. Prenons l'exemple à la fin de ce post. Il y a entre eux deux classes, les instances dont contiennent des références. Dans ces conditions, il n'y a aucune possibilité que les constructeurs désérialisation des deux instances sont passés avec des objets construits. Donc sérialiseur appelle d'abord l'un des constructeurs en passant il une instance déstructurés du second type et puis appelle le constructeur de cet objet, en passant, il construit instance de premier type. De cette manière, il nous aide à restaurer les connexions des objets, il est donc vraiment le meilleur qu'il peut faire!

Ensuite, callbacks OnDeserializing et OnDeserialized dans de tels cas peuvent être appelés comme je l'ai souligné dans la question, tandis que la méthode de OnDeserialization de IDeserializationCallback est toujours appelé après les objets COMPLETS graphique a été désérialisés, exactement comme il est indiqué dans sa spécification.

Garder tout ce qui précède à l'esprit, je trouve la meilleure utilisation à l'interface de IDeserializationCallback faire tout traitement post-désérialisation j'ai besoin. Dans ce cas, je suis sûr que les constructeurs sont appelés pour tous les objets et je peux faire les adaptations nécessaires, d'une manière « sûre ».

      [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);
      }
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top