编程语言
首页 > 编程语言> > 如何从自定义目录(包括其依赖项)动态加载程序集?

如何从自定义目录(包括其依赖项)动态加载程序集?

作者:互联网

我发现以下代码可从自定义位置动态加载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)后返回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;
}

标签:net-assembly,resolve,assembly-resolution,c,net
来源: https://codeday.me/bug/20191031/1973279.html