views:

1029

answers:

3

I have a class that maintans a reference to a Hashtable and serializes/deserializes that Hashtable. After the call to SerializationInfo.GetValue, the Hashtable is not fully deserialized because the deserialization happens during the IDeserialization calback.

Hashtable hashtable = (Hashtable) info.GetValue("hash", typeof(Hashtable));

I also implemented the IDeserialization callback in the parent class, but there too the Hashtable is not fully deserialized yet. I expected it to be if the deserialization is happening from the inside out.

My question is, is it safe to explicitely call Hashtable.OnDeserialization from the OnDeserialization method of my parent class, so that I can enumerate it at that point?

public virtual void OnDeserialization(object sender)
{
    hashtable.OnDeserialization(sender);
}
A: 

I have a class that references a couple of hashtables and the whole class serializes and deserializes without issues. I do not have hooks into the OnDeserialization callback. The code is relatively simple:

class foo: ISerializable
{
Hashtable hash;
public foo(SerializationInfo Info, StreamingContext Context)
{
hash = (Hashtable)Info.GetValue("hash", typeof(Hashtable));
}
//other junk
}

the caller that de/serializes the object is plain vanilla:

MemoryStream stream = new MemoryStream();
BinaryFormatter serializer = new BinaryFormatter();
serializer.Serialize(stream, objFoo);

and

//get stream from somewhere
foo objFoo = (foo)serializer.Deserialize(stream);

The other thing to look for is that everything in your hashtable needs to be serializable. See if this helps, otherwise post more code samples to see what the issue is.

mark w
+1  A: 

I suspect you have already googled, but I happened to across this pattern yesterday.

public BoringClass(SerializationInfo info, StreamingContext context)
{
    Hashtable hashtable = (Hashtable) info.GetValue("hash", typeof(Hashtable));
    hashtable.OnDeserialization(this);

    Console.WriteLine("Value is: " + hashtable["testItem"]);

}
Brian Adams
Good idea, this helps with a similar problem that I have had. You have to make sure that OnDeserialization is safe to call twice, though.
Joel in Gö
+3  A: 

This is really an interesting issue. After checking the serialization code with Reflector, I think that there is no generally good soluiton if a referred class uses IDeserializationCallback.

Probably you have seen, that there are two other ways as well to run some code during deserialization, the [OnDeserializing] and the [OnDeserialized] attributes. Unfortuanately both runs before the IDeserializationCallback.OnDeserialization(). This is the run order of the methods if you have class1 that refers to a class2:

Class1: [OnDeserializing]
Class2: [OnDeserializing]
Class2: [OnDeserialized]
Class1: [OnDeserialized]
Class1: IDeserializationCallback.OnDeserialization
Class2: IDeserializationCallback.OnDeserialization

As you can see, the [OnDeserializing] and the [OnDeserialized] attributes work consistent, but the IDeserializationCallback methods not really... :(

I have also checked the OnDeserialization implementation of Hashtable and Dictionary, and both seems to be safe for calling the OnDeserialization more than once (only the first call will perform the necessary operation, the subsequent calls will do nothing).

So finally you should call the OnDeserialization() of the Hashtable, as Sean and Brian suggested.

Gaspar Nagy