views:

56

answers:

3

I have a VS Add-In that's using a BinaryFormatter to deserialize an object. To resolve the type of this object, it's calling Assembly.Load(objectTypeFullName) but it's triggering an exception because Assembly.Load cannot find the assembly in any of the places it's searching on. The given assembly is sibling to the add-in assembly, but it seems that Assembly.Load() can't find it there.

A possible solution would be to determine where Assembly.Load should look for assemblies.

What should I do?

PS: I'm trying not to put this assembly on GAC because I would need to update it everytime I recompile the assembly.

+3  A: 

You can use AppDomainSetup.PrivateBinPath to add additional private search paths. This can be retrieved via AppDomain.SetupInformation.

Another option is to subscribe to AppDomain.AssemblyResolve in order to override the behavior when it fails to find your assembly.

Reed Copsey
Thank you Reed. Some notes: Even though AppDomain.AppendPrivatePath is deprecated in favor of AppDomainSetup.PrivateBinPath, I could only use the first. AppDomainSetup.PrivateBinPath remains null after I alter it. AppDomain.AppendPrivatePath lets me to add any path THAT IS A CHILD OF the AppDomain.BaseDirectory, which in many cases is sufficient, not in mine because my BaseDirectory is DevEnv directory. The other solution, AppDomain.AssemblyResolve is good enough. Notes: The event is only called when .NET can't resolve the assembly for itself. If all handlers return null,an exception is thrown
Ciwee
+2  A: 

If you are just trying to determine where the assembly loader is trying to load your dll from, I recommend that you turn on the fusion logs. Doing so will enable you to get output that will show you each path that was checked for the corresponding dll.

There is an MSDN article on how to configure the fusion logs, and a useful article by Suzanne Cook on how to debug loading failures. If you turn on LogFailures and you should only get output for assemblies that failed to be loaded.

adrianbanks
Very interesting this fusion logs, I'm reading the article. Thanks.
Ciwee
+1  A: 

Here's a code snippet showing how AssemblyResolve might be used to resolve your assembly (as per Reed Copey's answer):

// register to listen to all assembly resolving attempts:
 AppDomain currentDomain = AppDomain.CurrentDomain;
 currentDomain.AssemblyResolve += new ResolveEventHandler(MyResolveEventHandler);


 // Check whether the desired assembly is already loaded
 private static Assembly MyResolveEventHandler(object sender, ResolveEventArgs args) {
    string desiredAssmebly = args.Name;
    if (desiredAssembly.Equals("NameUsedToLoadMyAssembly")){
        return Assembly.LoadFrom(myAssemblyPath);
    }

    return null;
  }

Also, note that the MSDN page for AssemblyResolve states that:

Beginning with the .NET Framework version 4, the ResolveEventArgs.RequestingAssembly property returns the assembly that requested the assembly load that could not be resolved...

This can be used if you know your assembly's location relative to that of the requesting assembly.

Hershi
Hershi, thanks +1. In fact your solution turned out to be the one I used, and I ended up using your snippet. I marked Reed's answer as accepted as it's more complete. Thank you anyway.
Ciwee