2010-10-26 7 views
6

Come indica MSDN here, è possibile. Ma ho passato 2 ore a scavare codice mscorlib, perché in alcuni casi il BinaryFormatter ha chiamato il mio metodo contrassegnato con il costruttore di deserializzazione PRIMA di OnDeserialized. Cioè, l'ordine eraÈ possibile utilizzare OnDeserializedAttribute anziché l'interfaccia IDeserializationCallback?

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

Mentre mi aspettavo che fosse

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

E il punto finale. Quando ho implementato l'interfaccia IDeserializationCallback, il suo metodo OnDeserialization è stato chiamato AFTER costruttore, come volevo e mi aspettavo.

Ho cercato di riprodurlo su una semplice struttura di classe, ma lì tutto ha funzionato bene. Nel nostro progetto il grafico degli oggetti che viene serializzato è molto complesso, quindi non so dove scavare. Ispezionare il codice mscorlib con il riflettore non è stato di grande aiuto - il codice di deserializzazione è troppo complicato per me per capire da dove viene il problema.

Quindi, qualcuno sa che cosa potrebbe causare questo problema? Usiamo il presupposto che OnDeserialized è chiamato PRIMA del costruttore in molti altri posti quindi sono spaventato ora che non è molto affidabile ...

Grazie!

risposta

5

Infine, ho la risposta alla mia domanda, se qualcuno fosse interessato. Considera l'esempio alla fine di questo post. Esistono due classi, le cui istanze contengono riferimenti l'una all'altra. In tali condizioni non vi è alcuna possibilità che i costruttori di deserializzazione di entrambe le istanze siano passati con oggetti costruiti. Quindi serializzatore prima chiama uno dei costruttori passandogli un'istanza non strutturata di secondo tipo e quindi chiama il costruttore di quell'oggetto, passandogli un'istanza costruita di primo tipo. In questo modo ci aiuta a ripristinare le connessioni degli oggetti, quindi è davvero il meglio che può fare!

Avanti, OnDeserializing e OnDeserialized callback in tali casi possono essere chiamati come ho sottolineato nell'interrogazione, mentre OnDeserialization metodo IDeserializationCallback viene sempre chiamato dopo che il grafico oggetti COMPLETE è stato deserializzati, esattamente come viene indicato nella sua specifica.

Tenendo tutto ciò a mente, trovo il modo migliore di utilizzare l'interfaccia IDeserializationCallback per eseguire qualsiasi elaborazione di post-deserializzazione di cui ho bisogno. In tal caso sono sicuro che i costruttori sono chiamati a tutti gli oggetti e posso apportare le necessarie modifiche in un modo "sicuro".

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