.NET Framework Developer Center > .NET Development Forums > .NET Remoting and Runtime Serialization > IDeserializationCallback.OnDeserialization call sequence
Ask a questionAsk a question
 

Proposed AnswerIDeserializationCallback.OnDeserialization call sequence

  • Monday, January 14, 2008 10:45 AMrajeev511 Users MedalsUsers MedalsUsers MedalsUsers MedalsUsers Medals
     
    Hi,

    I wanted to know what is the sequence of calls made to types implementing IDeserializationCallback.

    As in if there is a type called A implementing
    IDeserializationCallback and suppose it contains an object of type B also implementing IDeserializationCallback, then during the deserialization of an object of type A shouldn't the call to B.OnDeserialization be made before A.OnDeserialization ?

    If yes, its not happening. If no, then why?
    Also is there any way to force this sequence of calls.

    Any help would be highly appreciated.
    Thank you in advance.

All Replies

  • Monday, January 14, 2008 11:23 AMIndian Ocean Users MedalsUsers MedalsUsers MedalsUsers MedalsUsers Medals
     

     

    Hi,

     

    Not getting this question properly... Can y ou explain a bit more using some code snippet you may have... it can help me to solve problem.

     

     

  • Monday, January 14, 2008 2:17 PMrajeev511 Users MedalsUsers MedalsUsers MedalsUsers MedalsUsers Medals
     
    [Serializable]
        public class A : IDeserializationCallback
        {
            B b = new B();

            public void OnDeserialization(object sender)
            { }
        }

        [Serializable]
        public class B : IDeserializationCallback
        {
            public void OnDeserialization(object sender)
            { }
        }



    Ok to explain myself here is the code snippet.
    Now if you serialize an instance of A and then deserialize it, the call goes to the OnDeserialization on A before going to OnDeserialization of B. Shouldnt it be the other way round ?
  • Thursday, January 24, 2008 5:03 PMIndian Ocean Users MedalsUsers MedalsUsers MedalsUsers MedalsUsers Medals
     

     

    How you are calling A and B's respective methods?

    Your answer can help me to answer your question.

     

     

  • Tuesday, January 29, 2008 8:35 AMrajeev511 Users MedalsUsers MedalsUsers MedalsUsers MedalsUsers Medals
     
    public static void Main(string[] args)
            {
                A a = new A();                       
                MemoryStream ms = new MemoryStream();
                BinaryFormatter bf = new BinaryFormatter();
                ms.Seek(0, SeekOrigin.Begin);
                bf.Serialize(ms, a);
                ms.Seek(0, SeekOrigin.Begin);
                bf.Deserialize(ms);           
            }


            [Serializable]
            public class A : IDeserializationCallback
            {
                B b = new B();

                public void OnDeserialization(object sender)
                {
                    Console.WriteLine("I am in A");
                }
            }

            [Serializable]
            public class B : IDeserializationCallback
            {
                public void OnDeserialization(object sender)
                {
                    Console.WriteLine("I am in B");
                }
            }


    Put this in a class and execute.
    You will notice that "I am in A" will be printed before "I am in B".
    My question is who decides this sequence. And logically shouldnt
    it be printed the other way round ?

  • Monday, March 17, 2008 8:14 AMIndian Ocean Users MedalsUsers MedalsUsers MedalsUsers MedalsUsers Medals
     

    Hi,

    I am not sure who decides the sequence but what is happening is proper i think.

    You are creating A's serialization so obvious effect is, when you deserialize, first it will call A's OnDeserialization and then it will go through each member if any and call OnDeserialization on them.

     

    Please let me know your further queries,

     

    HTH

  • Monday, March 17, 2008 8:49 PMSowmy SrinivasanModeratorUsers MedalsUsers MedalsUsers MedalsUsers MedalsUsers Medals
     

    The only guarantee is that IDeserializationCallback is called at the end of deserialization. The within an object is not guaranteed. Your best bet is to have a reference to the other object and fixup both when the second one is called.

    Sowmy

    • Unmarked As Answer byrajeev511 Thursday, October 30, 2008 6:56 AM
    • Unmarked As Answer byrajeev511 Thursday, October 30, 2008 6:56 AM
    •  
  • Wednesday, March 19, 2008 6:48 PMrajeev511 Users MedalsUsers MedalsUsers MedalsUsers MedalsUsers Medals
     

    "The only guarantee is that IDeserializationCallback is called at the end of deserialization"

    How can you say that (in the example above) A is 'deserialized' when the member b inside it is still not deserialized ?

     

    "The within an object is not guaranteed"

    Could you please explain

     

    "Your best bet is to have a reference to the other object and fixup both when the second one is called"

    This is not a practical solution. Also by 'fixing' do you mean calling the OnDeserialized of the 'other object' manually ?

    If yes i dont think its a very good option.

  • Friday, March 21, 2008 2:40 AMSowmy SrinivasanModeratorUsers MedalsUsers MedalsUsers MedalsUsers MedalsUsers Medals
     

     

    "The only guarantee is that IDeserializationCallback is called at the end of deserialization"

    >>How can you say that (in the example above) A is 'deserialized' when the member b inside it is still not deserialized ?

    Calling OnDeserialized is just a notificiation that serialization has completed. As far as the serializer is concerned the serialization is complete

     

    "The within an object is not guaranteed"

    >>Could you please explain

     

    I am sorry, i meant the order of calling within an object graph is not guaranteed.

     

    "Your best bet is to have a reference to the other object and fixup both when the second one is called"

    >>This is not a practical solution. Also by 'fixing' do you mean calling the OnDeserialized of the 'other object' manually ?

    If yes i dont think its a very good option.

    Unfortunately I cannot think of any better solution using OnDeserialized

  • Wednesday, November 04, 2009 3:59 PMArchimagus Users MedalsUsers MedalsUsers MedalsUsers MedalsUsers Medals
     Proposed Answer
    IDeserializationCallback is called at the end of serialization.  I don't know of any way to force the order.

    If you need more control, instead of using IDeserializationCallback, use ISerializable which will get you the method

    In A
    public void GetObjectData(SerializationInfo info, StreamingContext context)
    {
    info.AddValue("b", b);
    //add the rest of A's serialized members here.
    }

    In B
    public void GetObjectData(SerializationInfo info, StreamingContext context)
    {
    //add B's serialized members here.
    }

    You will also need to implement a deserialization constructor.

    public A(SerializationInfo info, StreamingContext context)
    {
    b = info.GetValue("b", typeof(B)) as B;
    // Get the rest of A's serialized items here.
    }

    Again, also add this to B to deserialize the members of B.
    public A(SerializationInfo info, StreamingContext context)
    {
    // Get B's serialized items here.
    }

    Now, when the constructor of A calls get value on B,  B will be deserialized,  by getting info on B in the top of A's constructor you are in effect causing B to deserialize first.

    I realize this is a bit late, but It may help some other people with similar problems.
    • Proposed As Answer byArchimagus Wednesday, November 04, 2009 3:59 PM
    •  
  • Tuesday, November 24, 2009 8:59 PMToolmakerSteve Users MedalsUsers MedalsUsers MedalsUsers MedalsUsers Medals
     
    Glad I saw this thread. I'll agree with original poster - if IDeserializationCallback is unable to unwind from bottom to top, that limits its usefulness in complex situations. That means that the outer object A has no guarantee that inner objects are fully deserialized before its callback occurs. That seems .. undesirable.

    I appreciate the example of using ISerializable - at least it works - but I'm not keen on having to write special constructors for the HUNDREDS of classes involved in the complex application I am working with.   Hopefully most of the classes can be serialized by just marking a few properties with attributes, allowing most to be default.

    Currently noodling around an approach using ISerializationSurrogate, but that has the opposite problem - seems too centralized, may not cope well with evolution of the app.