c# - 如何从自定义目录动态加载程序集,包括其依赖项?

标签 c# .net .net-assembly assembly-resolution resolve

我发现了以下从自定义位置动态加载 dll 的代码:

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);
    }
}

在某些情况下,此解决方案有效,但对于 ZipDotNet dll,我得到:

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}


因为它传递 if (File.Exists(assemblyPath) == false) return null; 我猜它是加载 Ionic.Zip.dll 的依赖项的问题?我也将如何解决它们?

最佳答案

查看Iconic.Zip.dll 的源代码here ,我看到项目中唯一的引用是 System、System.Data、System.Security 和 System.Xml,所以我怀疑原因是您无法加载它的任何引用。

我认为您的程序集解析方法有点太简单了。它假设程序集名称与文件名相同,但情况并非总是如此。因此,您可以为目标文件夹中的每个 dll 获取 AssemblyName 并将名称映射存储到文件中。然后,当解析器请求一个名称时,您可以在已知名称中查找它并加载程序集文件。这是该想法的快速实现。

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;
}

关于c# - 如何从自定义目录动态加载程序集,包括其依赖项?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15494655/

相关文章:

c# - 通过等待任务或访问其 Exception 属性未观察到任务的异常

c# - 是否可以更改 Winforms 组合框以禁止在其中输入内容?

c# - ListChanged 时刷新 UltraGrid 的 GroupBy Sort 子带?

c# - 哪种代码流模式在C#/。NET中更有效?

c# - 使用数字签名对强命名程序集进行签名是一种不好的做法吗?

c# - 从数组中只选择最好的项目

c# - 使用 OpenXML SDK 2.0 将页眉和页脚添加到现有的空 word 文档

c# - System.Timers.Timer 仅提供每秒最多 64 帧

.net - 您如何管理 bdd 功能和方案?

c# - 自动递增 AssemblyInformationalVersion