Also, note that if you use LoadFrom you'll likely get a FileNotFound exception because the Assembly resolver will attempt to find the assembly you're loading in the GAC or the current application's bin folder. Use LoadFile to load an arbitrary assembly file instead--but note that if you do this you'll need to load any dependencies yourself.

I've found that although this works most of the time, in some cases you actually still need to attach a handler to the AppDomain.CurrentDomain.AssemblyResolve event as described in this MSDN answer. In my case, I was trying to hook into the SpecRun deployment running under MSTest, but I think it applies to many situations in which your code might not run from the "primary" AppDomain - VS extensions, MSTest, etc.
–
AaronaughtJan 13 '14 at 4:06

Ah interesting. I'll look into that and see if I can make that slightly easier to work with via ADT. Sorry that code's been slightly dead for a while now--we all have day jobs :).
–
JduvFeb 4 '14 at 16:58

@Jduv Would upvote your comment about 100 times if I could. Your library helped me solve a seemingly unsolvable problem I was having with dynamic assembly loading under MSBuild. You should promote it to an answer!
–
Philip DanielsJul 28 '14 at 20:08

A MarshalByRefObject can be passed around appdomains. So I would guess that Assembly.LoadFrom tries to load the assembly in a new appdomain, what is only possible, if the calling object could be passed between those appdomains. This is also called remoting as described here: msdn.microsoft.com/en-us/library/…
–
Christoph MeißnerJun 29 '12 at 0:48

21

This doesn't work. If you execute the code and check the AppDomain.CurrentDomain.GetAssemblies() you'll see that the target assembly you're attempting to load is loaded into the current application domain and not the proxy one.
–
JduvNov 13 '12 at 4:41

17

This is complete nonsense. Inheriting from MarshalByRefObject doesn't magically make it load in every other AppDomain, it just tells the .NET framework to create a transparent remoting proxy instead of using serialization when you unwrap the reference from one AppDomain in another AppDomain (the typical way being the CreateInstanceAndUnwrap method). Can't believe this answer has over 30 upvotes; the code here just a pointlessly roundabout way of calling Assembly.LoadFrom.
–
AaronaughtJan 13 '14 at 4:00

Once you pass the assembly instance back to the caller domain, the caller domain will try to load it! This is why you get the exception. (This happens in your last line of code

domain.Load(AssemblyName.GetAssemblyName(path));

Thus, whatever you want to do with the assembly, should be done in a proxy class - a class which inherit MarshalByRefObject.

Take in count that the caller domain and the new created domain should both have access to the proxy class assembly. If your issue is not too complicated, consider leaving the ApplicationBase folder unchanged, so it will be same as the caller domain folder (the new domain will only load Assemblies it needs).

Why do I have to load the assembly by using a proxy class? What is the difference compared to loading it using Assembly.LoadFrom(string). I am interested in the technical details, from the CLR's perspective. I would be very grateful if you could provide an answer.
–
GinoBambinoMar 12 at 18:17

You use the proxy class in order to avoid the new assembly from being loaded in to your caller domain. If you'll use Assembly.LoadFrom(string), the caller domain will try to load the new assembly references and won't find them because it doesn't search for assemblies in the "[AsmPath]". (msdn.microsoft.com/en-us/library/yx7xezcf%28v=vs.110%29.aspx)
–
NirMar 14 at 0:19

You need to handle the AppDomain.AssemblyResolve or AppDomain.ReflectionOnlyAssemblyResolve events (depending on which load you're doing) in case the referenced assembly is not in the GAC or on the CLR's probing path.

It took me a while to understand @user1996230's answer so I decided to provide a more explicit example. In the below example I make a proxy for an object loaded in another AppDomain and call a method on that object from another domain.