How to get BinaryFormatter to deserialize in a different application
Asked Answered
T

5

21

I am using BinaryFormatter to serialize an array of class instances to a file. I can deserialize this fine within the same application. When I try the same deserialization in a different application (that pulls in a common file that does the work) then I get the following error:

{"Could not load file or assembly 'pmlscan, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null' or one of its dependencies. The module was expected to contain an assembly manifest."}

where pmlscan is the name of the original application. How do I get BinaryFormatter to not try and load pmlscan?

Thorman answered 16/11, 2010 at 12:7 Comment(1)
See also: the "Overriding Assembly / Type information" section of Binary SerializationJessalyn
M
21

You can achieve it by using custom SerializationBinder. See here: Advanced Binary Serialization: Deserializing an Object Into a Different Type Than the One It was Serialized Into

Mcnulty answered 23/9, 2011 at 20:58 Comment(1)
While that article is very good (thanks for the link), note that this answer is pretty much a link-only answer; could you add some more content from the page into your answer in case the article disappears?Jessalyn
R
3

The binary serializer encodes class and assembly information into a binary array. When you deserialize this array, the deserializer uses this information to locate the assembly the class resides in, and (if necessary) loads the assembly into you app domain. If the other application doesn't have access to the assembly that the class type resides in then you'll see the error you're getting.

As mentioned by another poster, put these common classes into a shared assembly and deploy them to the client/other application as well as the server application.

Rochelle answered 16/11, 2010 at 12:32 Comment(1)
Well, you can always resolve to another assembly and compatible type for deserialization. That works, but not for the weak at heart.I
B
3

If the classes are the same, and it's just another assembly, you could try adding an assemblyBinding section to you .config file.

You should also read the article about Resolving Assembly Loads and the TypeResolve event.

Using these techniques you can redirect the .Net typesystem to another type while deserializing.

Note: Migrating your shared classes to a shared .dll will be a more easy solution.

Bulwark answered 16/11, 2010 at 12:58 Comment(0)
R
3
sealed class PreMergeToMergedDeserializationBinder : SerializationBinder
{
    public override Type BindToType(string assemblyName, string typeName)
    {
        return Type.GetType("BinarySerialization.YourClass");
    }
}
BinaryFormatter bfDeserialize = new BinaryFormatter();
bfDeserialize.Binder = new PreMergeToMergedDeserializationBinder();
while (fsRead.Position < fsRead.Length)
{
    YourClass sibla = (YourClass)bfDeserialize.Deserialize(fsRead);
}

Assuming you have an exe that serializes data in your "YourClass" and an another exe that de-serializes the YourClass objects.

Rosy answered 1/9, 2014 at 12:38 Comment(0)
C
-1

You cannot!

Best option is to publish your serializable classes in a separate assembly and you refer to it in server (serializer) and client (deserializer). This way you are not publishing the whole of your source code to the outside world.

Curet answered 16/11, 2010 at 12:14 Comment(4)
You are talking about .Net here. Everything is possible. (Although the separate assembly is the easiest).Bulwark
The problem is not trying to load and failing. Question is "not try and load pmlscan".Curet
Using assemblyRedirect you do not try to load pmlscan. But saying "You cannot!", that's not correct. Since this is a complex matter, I forgive you and did not downvote you for it ;-)Bulwark
You can! I did it right now a it works like a charm :). (I use Binder.)Forefoot

© 2022 - 2024 — McMap. All rights reserved.