BinaryFormatter.Deserialize "unable to find assembly" after ILMerge

Mike Park picture Mike Park · Mar 2, 2011 · Viewed 23.7k times · Source

I have a C# solution with a referenced dll (also C# with the same .Net version). When I build the solution and run the resulting exe, without merging the exe and the referenced dll, everything works fine.

Now I want to merge these into one exe. I run ILMerge and everything appears to work ok. I try to execute the exe and it seems to run just fine until it tries to deserialize an object defined in the referenced dll.

using (Stream fstream = new FileStream(file_path, FileMode.Open))
{
    BinaryFormatter bf = new BinaryFormatter();
    return bf.Deserialize(fstream) as ControlledRuleCollection; 
    // throws unable to find assembly exception
}

Is there maybe some ILMerge option I'm missing here?

Answer

Phil picture Phil · Jan 26, 2012

You can do this by creating and adding a SerializationBinder sub class that will change the assembly name before the deserialization happens.

sealed class PreMergeToMergedDeserializationBinder : 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 exeAssembly = Assembly.GetExecutingAssembly().FullName;


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

        return typeToDeserialize;
    }
}

Then when deserializating add this to the BinaryFormatter:

BinaryFormatter bf = new BinaryFormatter();
bf.Binder = new PreMergeToMergedDeserializationBinder();
object obj = bf.Deserialize(ms);