Deserialization, Surrogate and WeakReference

A

Alex Zhitlenok

Hi,
In our system, we use a lot of referenced objects. We use binary
serialization for saving the objects and deserialization for
restoring. It worked, and we had no problem.

In a new version of our system, a lot of changes were done: some
classes were moved from assembly to assembly, others changed their
names, or have the same names but changed their fields list.
Obviously, the new version must read files that were saved in the
previous version.

To do that, I
1. Implemented empty surrogate classes for all classes that were
serialized;
2. Created Binder that binds all old types to new surrogate types;
3. Created BinaryFormatter and set its Binder property to my Binder
object.
4. Created surrogate deserializer object that implemented
SetObjectData(…) methods for each surrogate classes;
5. Created SurrogateSelector, which contains all my surrogate types
and corresponding surrogate deserializers.
6. SurrogateSelector property of the BinaryFormatter object was set to
my SurrogateSelector.

My first approach was just to deserialize binary stream to nothing,
add some necessary fields to my surrogate classes, and use them in
further restoring.

For all classes but one, the schema works fine. During
deserialization, old classes types are substituted with corresponded
surrogate classes types, SetObjectData(…) method is called for
surrogate deserialize and all info could be extracted from
SerializationInfo object.

Unfortunately one of the old classes was derived from WeakReference
class. After SetObjectData(…) is called for surrogate class, an
exception "Insufficient state to deserialize the object" is thrown.
Actually, I am not interested in this WeakReference object and would
be glad to skip its deserialization or ignore the exception.

Any suggestions are highly appreciated.

Here is some codes extraction (if someone wants to investigate the
problem I can send 30k binary stream).

//Binder
public class Assembly2AssemblyDeserializationBinder :
System.Runtime.Serialization.SerializationBinder
{
public override Type BindToType(String assemblyName, string
typeName)
{
//code to substitute all old classes with new ones
}
}

//Formatter Factory – returns BinaryFormatter and set surrogates for
//all new classes
public class V23FormatterFactory
{
public static IFormatter CreateVersionBinaryFormatter()
{
SurrogateSelector selector = new SurrogateSelector();
// adds all new surrogate classes types to selector and
// sets that V23Deserializer object must be used
selector.AddSurrogate( type,
new StreamingContext(StreamingContextStates.All),
new V23Deserializer());
BinaryFormatter bf = new BinaryFormatter();
bf.SurrogateSelector = selector;
return bf;
}
}

//surrogate deserialized
public class V23Deserializer : ISerializationSurrogate
{
public Object SetObjectData(
object obj,
SerializationInfo info,
StreamingContext context,
ISurrogateSelector selector
)
{
if( obj.GetType() == … )
{
//does nothing
}
else if( obj.GetType() == Type.GetType("SurrogateWeakRef"))
{
//does nothing
//and throws an exception "Insufficient state..."
//after the return
}
return obj;
}
}

//
// Main call for deserialization
//
IFormatter vFormatter =
V23FormatterFactory.CreateVersionBinaryFormatter();
vFormatter.Binder = new Assembly2AssemblyDeserializationBinder();
Object alSaved = vFormatter.Deserialize(sStream);
 
Y

Ying-Shen Yu[MSFT]

Hi Alex,

Thanks for posting in the community!

To my understanding now, You are using a surrogate class to do
serialization/de-serialization for the objects, You got
SerializationException when SetObjectData on an object derived from
WeakReference. If I misunderstood your problem, please feel free to let me
know.

It seems this issue is much close to .NET Remoting Technlogy, which is not
my specialty. Anyway, I'll try to help you on this issue, could you send me
a simple sample to reproduce this problem?

Also, we have a .NET Remoting discussion group
microsoft.public.dotnet.framework.remoting
You may also post a thread there, probably you could get a quick solution.
Thanks!

Best regards,

Ying-Shen Yu [MSFT]
Microsoft Online Partner Support
Get Secure! - www.microsoft.com/security

This posting is provided "AS IS" with no warranties and confers no rights.
This mail should not be replied directly, "online" should be removed before
sending.
 
A

Alex Zhitlenok

Hi Ying-Shen!
Thank you for your reply.
Briefly the problem is:
there is a previously created binary stream (a result of standard
binary serialization) that must be restored as much as possible in a
new version.
It could be done using Surrogates for all classes but
WeakReference-derived classes, which throw SerializationException.
WeakReference does not store any interesting info and could be
skipped.
The problem is how to do it?
As you kindly agreed to investigate the problem, I could send you the
stream (30K) and my codes. Just let me know the better way how to do
that.
At the same time, I'll try to place my question one more time to other
group according to your suggestion.
Thank you,
Alex
 
Y

Ying-Shen Yu[MSFT]

Hi Alex,

You may reach me by
(e-mail address removed)
Note, "online." should be removed before sending the mail.
Thanks, I'm looking forward to your sample.


Best regards,

Ying-Shen Yu [MSFT]
Microsoft Online Partner Support
Get Secure! - www.microsoft.com/security

This posting is provided "AS IS" with no warranties and confers no rights.
This mail should not be replied directly, "online" should be removed before
sending.
 
A

Alex Zhitlenok

Hi Alex,

You may reach me by
(e-mail address removed)
Note, "online." should be removed before sending the mail.
Thanks, I'm looking forward to your sample.


Best regards,

Ying-Shen Yu [MSFT]
Microsoft Online Partner Support
Get Secure! - www.microsoft.com/security

This posting is provided "AS IS" with no warranties and confers no rights.
This mail should not be replied directly, "online" should be removed before
sending.
Hi,
I do find a work around for the problem by myself.
In a serialization binary stream, they store some info about classes
that have been serialized. The well known problem is how to resolve
delegates. Fortunately, in my case, I have no needs to resolve
delegates but only to suppress delegates deserialization because it
throws an exception.
Looking through the stream I found that the problem related to the
class (likely undocumented) that named
"System.DelegateSerializationHolder". My first action was to create my
own surrogate class and substitute (for deserialization process) the
Microsoft class with my surrogate class. It helped me a little bit but
did not solve the problem because deserialization still tried to
resolve "System.DelegateSerializationHolder" somewhere.
Actually, system attempt to resolve a substituted class looks very
strange!
To avoid internal attempt to resolve
"System.DelegateSerializationHolder" class, I did an additional step
before starting deserialization. In the binary stream, I changed all
strings "System.DelegateSerializationHolder" to a new senseless one
(in my case with "SSSSSS.DelegateSerializationHolder". After that,
using surrogate technique, I substituted the non-existed class
"SSSSSS.DelegateSerializationHolder" with my surrogate. That case,
deserialization did not recognize SSSSSS.DelegateSerializationHolder
as its special class name and did not do any additional inner action.
So, at least, no exceptions were thrown.

I don't want to say that it's a good solution, but it is a solution.
Maybe, this technique could be used also for delegate resolving. Don't
know. I did not do any investigation.

By the way, is there any way to change ObjectManager object to my own?
I did not find any appropriate property?

Thank you,
Alex.
 
Z

Zach Kramer [MSFT]

Alex,

I am glad to see that you were able to work around the problem. I talked
with our development team and they said at this point there is no way to
override the base ObjectManager. Please let me know if there is anything
else that you need with this.

Thanks,
Zach Kramer
Microsoft C++/C# Support Professional
This posting is provided "AS IS" with no warranties and confers no rights.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top