If I was creating a new AppDomain this would be easy I could just add the search path to the AppDomainSetup when I create the domain. But in this case I wanted everything to be in one app domain so I couldn't do that.
The solution (that I found, there might be an easier way in which case please let me know) is to leverage closures and the AssemblyResolve event:
public static void LoadPackage(string dllPath, string className)
{string dllFullPath = Path.GetFullPath(dllPath);
var assembly = Assembly.LoadFile(dllFullPath);
var package = assembly.CreateInstance(className);if (null == package)
{throw new Exception("Couldn't load type " + className + " from " + dllPath);
}
var asembliesInDirectory = new Dictionary<string, string>();
foreach (string file in Directory.GetFiles(Path.GetDirectoryName(dllFullPath), "*.dll"))
{ try { asembliesInDirectory.Add(AssemblyName.GetAssemblyName(file).FullName, file);}
catch{}}
AppDomain.CurrentDomain.AssemblyResolve += (sender, eventArgs) => { if (!asembliesInDirectory.ContainsKey(eventArgs.Name)) {return null;
}
return Assembly.LoadFile(asembliesInDirectory[eventArgs.Name]);
};
}
The AssemblyResolve event gets called when the CLR find an assembly it needs to load. Handling this event lets you add your own assembly resolving logic into the process. This code will check the directory you loaded your first dll from any time the CLR can't find a dll. The reason for the dictionary is purely for performance, it is expensive to scan the directory every time you are trying to load something. So this just pre-caches all the assembly names for easy lookup.
0 comments:
Post a Comment