IDeserializationCallback.OnDeserialization call sequence
- 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
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.
- [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 ? How you are calling A and B's respective methods?
Your answer can help me to answer your question.
- 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 ? 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
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
"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.
"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
- 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 methodIn Apublic void GetObjectData(SerializationInfo info, StreamingContext context){info.AddValue("b", b);//add the rest of A's serialized members here.}In Bpublic 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
- 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.


