I have an in-memory assembly MyAssembly (class library) that is used in my main assembly MyApp.exe:
byte[] assemblyData = GetAssemblyDataFromSomewhere();
(For testing, the GetAssemblyDataFromSomewhere method can just do File.ReadAllBytes for an existing assembly file, but in my real app there is no file.)
MyAssembly has only .NET Framework references and has no dependencies to any other user code.
I can load this assembly into the current (default) AppDomain:
Assembly.Load(assemblyData);
// this works
var obj = Activator.CreateInstance("MyAssembly", "MyNamespace.MyType").Unwrap();
Now, I want to load this assembly into a different AppDomain and instantiate the class there. MyNamespace.MyType is derived from MarshalByRefObject, so I can share the instance across the app domains.
var newAppDomain = AppDomain.CreateDomain("DifferentAppDomain");
// this doesn't really work...
newAppDomain.Load(assemblyData);
// ...because this throws a FileNotFoundException
var obj = newAppDomain.CreateInstanceAndUnwrap("MyAssembly", "MyNamespace.MyType");
Yes, I know there is a note in the AppDomain.Load docs:
This method should be used only to load an assembly into the current application domain.
Yes, it should be used for that, but...
If the current
AppDomainobject represents application domain A, and theLoadmethod is called from application domain B, the assembly is loaded into both application domains.
I can live with that. There's no problem for me if the assembly will be loaded into both app domains (because I actually load it into the default app domain anyway).
I can see that assembly loaded into the new app domain. Kind of.
var assemblies = newAppDomain.GetAssemblies().Select(a => a.GetName().Name);
Console.WriteLine(string.Join("\r\n", assemblies));
This gives me:
mscorlib
MyAssembly
But trying to instantiate the class always leads to a FileNotFoundException, because the CLR tries to load the assembly from file (despite it is already loaded, at least according to AppDomain.GetAssemblies).
I could do this in MyApp.exe:
newAppDomain.AssemblyResolve += CustomResolver;
private static Assembly CustomResolver(object sender, ResolveEventArgs e)
{
    byte[] assemblyData = GetAssemblyDataFromSomewhere();
    return Assembly.Load(assemblyData);
}
This works, but this causes the second app domain to load the calling assembly (MyApp.exe) from file. It happens because that app domain now needs the code (the CustomResolver method) form the calling assembly.
I could move the app domain creation logic and the event handler into a different assembly, e.g. MyAppServices.dll, so the new app domain will load that assembly instead of MyApp.exe.
However, I want to avoid the file system access to my app's directory at any cost: the new app domain must not load any user assemblies from files.
I also tried AppDomain.DefineDynamicAssembly, but that did't work either, because the return value's type System.Reflection.Emit.AssemblyBuilder is neither MarshalByRefObject nor marked with [Serializable].
Is there any way to load an assembly from byte array into a non-default AppDomain without loading the calling assembly from file into that app domain? Actually, without any file system access to my app's directory?
 
    
 
     
    