I have a side project on reflection where I try to reproduce Lutz Roeder’s Reflector in such a way as to allow me to inspect several issues within my projects. This has led me to research into all kinds of issues from MSIL to C# code model and Reflection, the latest one becoming one of my favorite topics from .NET technologies.
My lattest hurdle was to overcome the devious “FileNotFoundException” when trying to resolve a type which is not in the main loaded assembly for reflection.
What happens? Let’s suppose you load an assembly which you want to inspect using reflection. You would use something like:
Assembly assembly = Assembly.LoadFile(path);
Type[] types = assembly.GetTypes();
MethodInfo[] methods = types[0].GetMethods();
ParameterInfo[] parameters = methods[0].GetParameters();
Then you start the usual work of gettting the types and then get the methods of one of the types and then of course try to see something like the parameters of one of the methods. Ain’t reflection great?
NO. Not if you don’t know how to use it. Because when you hit the line where you want to load the parameters of a method, the application will crash with a “FileNotFoundException” when the dll inspected is not in the same directory as the executable that is loading that assembly. Why the hell is that happening. Well I scoured the net for an answer and all where giving partial responses but none were actually giving me a sollution.
Let’s consider the following.
namespace A
{
public class C1
{
}
}
namespace B
{
public class C2
{
public void MyMethod(A.C1 param1)
{
}
}
}
And let’s consider that the namespaces A and B are declared in separate projects and thus result in two different dlls and the project that defines namespace B references the project that defines namespace A.
Now you want to load the “B.dll” to inspect the parameters from method “MyMethod” and you use the code I described above. Here the runtime will fail because he does not have a definition of the class C1, only of the class C2 which he already loaded and he will try to load the dll from the current directory (the directory of the running assembly – not A or B, but you program which inspects B). If the “A.dll” is not located there he will try in GAC and if that fails he will throw an exception. How do you fix this? Well you have the choice to copy the “A.dll” in your running directory or registed in GAC but hell, it is not nice and sometimes not possible.
What you can do is to instruct the application domain to call a custom method defined by you when he needs to load an assembly.
AppDomain.CurrentDomain.AssemblyResolve += new ResolveEventHandler(CurrentDomain_AssemblyResolve);
static Assembly CurrentDomain_AssemblyResolve(object sender, ResolveEventArgs args)
{
Assembly ass =
Assembly.LoadFile(AppDomain.CurrentDomain.RelativeSearchPath + args.Name.Substring(0, args.Name.IndexOf(“,”)) + “.dll”);
return ass;
}
What I told the domain here is to call tyeh CurrentDomain_AssemblyResolve method and there I made an assumption. When you compile the namespace B, in it’s debug directory the dll of namespace A is also copied. So if you load the assembly of namespace b from it’s debug directory, in the same directory we will have also the assembly of A. So we will load the assembly from there
Simple and effective. This approach solves also the error “Unable to load one or more of the requested types. Retrieve the LoaderExceptions property for more information.”
Cheers



Entries (RSS)
You are a god. Thank you!
this is the exactly the problem i’m getting but i’m having trouble plugging your solution in. Where does the code go? Do you have a noddy demo source code for this
You can plug it in the constructor of the class where you want to do the reflection.
Wow! Thank you very much!
I always wanted to write in my blog something like that. Can I take part of your post to my blog?
Of course, I will add backlink?
Sincerely, Timur I.
Wow, such a great article, I spent few days trying to find what am I doing wrong and why my libraries that I dynamically load using reflection do not work. I end up copying libraries into host directory. Now, I reverted them back. Great article!!!
Thanks a lot!!!
Leonard
I have another question though: If in your example dll B refferences dll A, why when you load dll B (using Assembly.LoadFile), A is not loaded automatically (because it was refferenced in B after all…)
Thanks
Leonard
Thanks for this useful article.
Thanks for this blog post. I was a bit confused searching how to handle referenced assemblies when using LoadFile.
2 Leonard: Read MSDN: Assembly.LoadFile does not resolve dependencies using the load path. I guess that’s where this blog post originated from actually.