I have a web service which searializes and returns the following to a client as an array of bytes:
[Serializable]
public class MyFile
{
public byte[] Data;
public string FileName;
}
That is, I return a List(Of MyFile) to the client.
It is consumed by the client with the following TYPENAME
System.Collections.Generic.List`1[[NorwayTaxService.Streaming+MyFile, NorwayTaxService, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null]]
with an assembly name of:
mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
I'm using the following two classes to bind to deserialize:
[Serializable]
public class MyFileLocal : ISerializable
{
public byte[] Data;
public string FileName;
// The security attribute demands that code that calls
// this method have permission to perform serialization.
[SecurityPermissionAttribute(SecurityAction.Demand, SerializationFormatter = true)]
void ISerializable.GetObjectData(SerializationInfo info, StreamingContext context)
{
info.AddValue("Data", Data);
info.AddValue("FileName", FileName);
}
// The security attribute demands that code that calls
// this method have permission to perform serialization.
[SecurityPermissionAttribute(SecurityAction.Demand, SerializationFormatter = true)]
private MyFileLocal(SerializationInfo info, StreamingContext context)
{
Data = (byte[])info.GetValue("Data", Data.GetType());
FileName = info.GetString("FileName");
}
}
sealed class MyFileWebToLocalVersionBinder : SerializationBinder
{
public override Type BindToType(string assemblyName, string typeName)
{
Type typeToDeserialize = null;
// For each assemblyName/typeName that you want to deserialize to
// a different type, set typeToDeserialize to the desired type.
String assemVer1 = Assembly.GetExecutingAssembly().FullName;
String typeVer1 = "NorwayTax.Streaming+MyFile";
if (assemblyName == assemVer1 && typeName == typeVer1)
{
// To use a type from a different assembly version,
// change the version number.
// To do this, uncomment the following line of code.
// assemblyName = assemblyName.Replace("1.0.0.0", "2.0.0.0");
// To use a different type from the same assembly,
// change the type name.
typeName = "MyFileLocal";
}
typeToDeserialize = Type.GetType(String.Format("{0}, {1}", typeName, assemblyName));
return typeToDeserialize;
}
}
But for the life of me, and trying many, many variations on the GETTYPE statement, my TYPE is always NULL.
For example, per a post on STACKOVERFLOW, I tried:
typeToDeserialize = Type.GetType(String.Format("{0}, {1}", "System.Collections.Generic.List`1[[NorwayTax.Streaming+MyFile, NorwayTax]]", assemblyName));
But it did not work :(
The object type I tried to deserialize didn't exist within client application / assembly. I thought that by using the
SerializationBinder
I'd be able to cast it into an a similar object.Here's the object, which is a serialized list / collection :
and perhaps it is possible to cast it into a similar collection but, for the life of me, I was unable to make it happen.
What I finally did was to isolate the above into its own DLL, which both my Web Service and client referenced and it worked flawlessly and without the need of the
SerializationBinder
.Finally, whole point of this exercise was to pass from the web service multiple files in one pass utilizing Framework tools. Interesting, the files I passed along are already compressed using 7z, but broken apart, per the business requirment, into an archive set (.001, .002, etc.).
The inspiration for my solution came from this answer: You should really define a class library with in it and reference that same assembly.