Signed Assembly and FormatterAssemblyStyle.Simple

  • Thread starter Thomas T. Veldhouse
  • Start date
T

Thomas T. Veldhouse

Hello.

I have been working with a client of mine on their seriazation code and we
seem to have run into an issue when we migrated from .NET 1.1 to .NET 2.0. We
have a framework of business objects that are serialized for persistant
storage. The object graph DOES change as development continues, but it is
required that we be able to deserialized existing classes and handle it
properly (version tolerance). With version 1.1 of the .NET framework, we were
able to create a custom formatter that used a custom SerializationSurrogate
and a custom SerializationBinder (as well as using
FormatterAssemblyStyle.Simple) to get this to work properly. Since, that
time, we have migrated to version 2.0 of the .NET framework, and now we are
finding that we can no longer take this approach due to an apparent, but
intended, defect in the serialization code of 2.0. Since many of the
assemblies in our framework are signed and strong-named (needed for use with
COM and Sharepoint), .NET is now simply ignoreing our request to use
FormatterAssemblyStyle.Simple.

Does anybody know of a way around this? I am fearful we are going to have to
roll our own serialization code that isn't based on .NET seriazation, which is
a horrific waste of our time.

Thank you in advance,
 
T

Thomas T. Veldhouse

Thomas T. Veldhouse said:
Does anybody know of a way around this? I am fearful we are going to have to
roll our own serialization code that isn't based on .NET seriazation, which is
a horrific waste of our time.

Well folks, I was able to get a work around, which hasn't solved the problem
entirely, as I still have an issue deserializing object graphs with class
instances that have an inheritance heirarchy which spans two or more strong
named assemblies.

I simply create a binder to thunk types over and use what is available in the
search path by removing all but the base assembly name. This binder is then
assigned to the formatter prior to deserialization:

sealed class SimpleDeserializationBinder : SerializationBinder
{
public override Type BindToType(string assemblyName, string typeName)
{
Type typeToDeserialize = null;

// replace assembly name with the simple assembly name
// - strip the strong name off of the name
assemblyName = assemblyName.Split(',')[0];

// The following line of code returns the type.
typeToDeserialize = Type.GetType(String.Format("{0}, {1}",
typeName, assemblyName));
return typeToDeserialize;
}
}

NOTE: this code has not been fully tested ;-) .. not too fond of using
String.Split()
 
T

Thomas T. Veldhouse

Thomas T. Veldhouse said:
NOTE: this code has not been fully tested ;-) .. not too fond of using
String.Split()

Hmm ... still having trouble! Why doesn't Microsoft honor "Simple" as the
documentation suggests? Anyway, here is the code we have now, but it STILL
doesn't work perfectly with subclasses of generic lists [themself generic]
being serialzied in an object graph where an the list is defined in one
assembly and the contents of the list are in another. Still, here is the code
we have so far, in case anybody google's this up in the future:

sealed class SimpleDeserializationBinder : SerializationBinder
{
private Regex _assemRegex = new Regex("(?<assembly>^.*?),.*");
private Regex _typeRegex = new
Regex("(?<type>.*?),(?<assembly>.*?),.*(?<end>]])");

public override Type BindToType(string assemblyName, string typeName)
{
// remove strong name from assembly
Match match = _assemRegex.Match(assemblyName);
if (match.Success)
{
assemblyName = match.Groups["assembly"].Value;
}

// remove strong name from any generic collections
match = _typeRegex.Match(typeName);
if (match.Success)
{
typeName = string.Format("{0},{1}{2}",
match.Groups["type"].Value,
match.Groups["assembly"].Value,
match.Groups["end"].Value);
}

Type typeToDeserialize = null;

// replace assembly name with the simple assembly name
// - strip the strong name off of the name
string type = string.Format("{0}, {1}", typeName,
assemblyName);

// The following line of code returns the type.
typeToDeserialize = Type.GetType(type);
return typeToDeserialize;
}
}

This code works for nearly all cases I have encountered, except what I
mentioned above, which is likely very rare.
 

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