I found the following code that loads a dll dynamically from a custom location:
private void Form1_Load(object sender, EventArgs e)
{
AppDomain currentDomain = AppDomain.CurrentDomain;
currentDomain.AssemblyResolve += new ResolveEventHandler(MyResolveEventHandler);
}
private Assembly MyResolveEventHandler(object sender, ResolveEventArgs args)
{
string folderPath = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location);
string assemblyPath = Path.Combine(folderPath, "libs", new AssemblyName(args.Name).Name + ".dll");
if (File.Exists(assemblyPath) == false) return null;
Assembly assembly = Assembly.LoadFrom(assemblyPath);
return assembly;
}
private void button1_Click(object sender, EventArgs e)
{
var zip = ZipFile.Read("test.zip");
foreach (ZipEntry file in zip)
{
file.Extract(".", ExtractExistingFileAction.OverwriteSilently);
}
}
In some cases this solution works, but with the ZipDotNet dll I'm getting:
InnerException {"File or assembly name \"Ionic.Zip, Version=1.9.1.8, Culture=neutral, PublicKeyToken=edbe51ad942a3f5c\" or one of its dependencies, was not found. Operation is not supported. (Exception from HRESULT: 0x80131515)":"Ionic.Zip, Version=1.9.1.8, Culture=neutral, PublicKeyToken=edbe51ad942a3f5c"} System.Exception {System.IO.FileLoadException}
Since its passing if (File.Exists(assemblyPath) == false) return null;
I' guessing its a problem with loading the depencies of Ionic.Zip.dll? How would I resolve them, too?
Looking at the source code of Iconic.Zip.dll here, I see that the only references in the project are to System, System.Data, System.Security, and System.Xml, so I doubt the reason is that you are unable to load any of its references.
I think your assembly resolve method is a little too simple. It is assuming the assembly name is the same as the file name, which is not always the case. So what you can do is get the AssemblyName
for each of the dlls in the target folder and store a mapping of names to files. Then when the resolver requests a name you look it up in your known names and load the assembly file. Here is a quick implementation of the idea.
private Dictionary<string, string> assemblyNameToFileMapping = new Dictionary<string, string>();
private void Form1_Load(object sender, EventArgs e)
{
GetAssemblyNames();
AppDomain currentDomain = AppDomain.CurrentDomain;
currentDomain.AssemblyResolve += new ResolveEventHandler(MyResolveEventHandler);
}
private void GetAssemblyNames()
{
string folderPath = Path.Combine(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location), "libs");
foreach(string file in Directory.EnumerateFiles(folderPath, "*.dll"))
{
try
{
AssemblyName name = AssemblyName.GetAssemblyName(file);
assemblyNameToFileMapping.Add(name.FullName, file);
}
catch { } // Just move on if we can't get the name.
}
}
private Assembly MyResolveEventHandler(object sender, ResolveEventArgs args)
{
string file;
if (assemblyNameToFileMapping.TryGetValue(args.Name, out file))
{
return Assembly.LoadFrom(file);
}
return null;
}
User contributions licensed under CC BY-SA 3.0