I have one assembly(MyAssembly.dll)(something like wrapper) which has a few references to other assemblies(3rdAssembly1.dll, 3rdAssembly2.dll). These referenced assemblies are embedded into my assembly as embedded resources. In my assembly I have main class(MyClass) which calls some functions from these third-party assemblies. This class has one default constructor where I try to resolve required dependencies as below:
public MyClass{
AppDomain.CurrentDomain.AssemblyResolve += new ResolveEventHandler(Resolver);
}
public static System.Reflection.Assembly Resolver(object sender, ResolveEventArgs args)
{
string source = "MyAssembly.Resources."+args.Name.Remove(args.Name.IndexOf(','))+".dll";
//source = "MyAssembly.Resources.3rdAssembly1.dll"
//source = "MyAssembly.Resources.3rdAssembly2.dll"
Assembly a1 = Assembly.GetExecutingAssembly();
Stream s = a1.GetManifestResourceStream(source);
byte[] block = new byte[s.Length];
s.Read(block, 0, block.Length);
Assembly a2 = Assembly.Load(block);
return a2;
}
Then I try to use my assembly(MyAssembly.dll) as embedded resource in my host app(MyApp.exe) where I also use Resolver
function.
static void main(string[] args){
AppDomain.CurrentDomain.AssemblyResolve += new ResolveEventHandler(MainResolver);
MyClass my = new MyClass();
my.DoWork();
}
static System.Reflection.Assembly MainResolver(object sender, ResolveEventArgs args)
{
string source = "MyApp.Resources."+args.Name.Remove(args.Name.IndexOf(','))+".dll";
//source = "MyApp.Resources.MyAssembly.dll"
Assembly a1 = Assembly.GetExecutingAssembly();
Stream s = a1.GetManifestResourceStream(args.Name);
byte[] block = new byte[s.Length];
s.Read(block, 0, block.Length);
Assembly a2 = Assembly.Load(block);
return a2;
}
The problem is my host app doesn't resolve internal assemblies(3rdAssembly1.dll, 3rdAssembly2.dll), because Resolver
function in MyClass is never called. The host app tries to resolve all of them and as a result fails. I played around with it and found out that if I exclude MyAssembly.dll from embedded resource and locate it in the same folder with host app, and replace += new ResolveEventHandler(MainResolver)
on += new ResolveEventHandler(MyClass.Resolver)
in main
function then it works!
It is necessary to have one assembly, because I'm going to use it in several apps and I don't want to include all referenced assemblies in all apps every time.
So, my question is how to resolve all dependencies(MyAssembly.dll and all internal ones which are contained in MyAssembly.dll as embedded resources) in host app?
Thanks in advance!
I solved this issue. When the host app runs and doesn't find required assembly, it calls AssemblyResolve
event. So, I have to use event handler called MainResolver
to load MyAssembly.dll
. Then before using methods of MyAssembly.dll
, it's necessary to remove it from AssemblyResolve
, because the app tries to resolve dependencies using ResolveEventHandler
in order which they were added (It calls MainResolver
and then Resolver
). As a result the host app fails, because it can't find required assemblies in MainResolver
. The solution is to reorder ResolveEventHandler
or remove MainResolver
from AssemblyResolve
after it was called. I think that exclude useless handler is easier.
So, I don't need to change anything in MyClass
. Everything I need is to add following code in host app before I create instance of MyClass
.
static MyApp(){
AppDomain.CurrentDomain.AssemblyResolve += new ResolveEventHandler(MainResolver);
}
static void main(string[] args){
//remove MainResolver
AppDomain.CurrentDomain.AssemblyResolve -= MainResolver;
MyClass my = new MyClass();
my.DoWork();
}
Now it works like a charm!