.NET Core 中的程序集加载 [英] Assembly Loading in .NET Core

查看:49
本文介绍了.NET Core 中的程序集加载的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

使用 VS2017 RC、.NET Core

Using VS2017 RC, .NET Core

我正在尝试从文件加载程序集.此程序集的依赖项在同一文件夹中.

I am trying to load an assembly from a file. The dependencies of this assembly are in the same folder.

我正在使用 AssemblyLoadContext.Default.LoadFromAssemblyPath.

我意识到 LoadFromAssemblyPath 只加载请求的程序集,忽略其依赖项;任何对程序集类型进行迭代的尝试都会失败,并返回 System.Reflection.ReflectionTypeLoadException.

I realize LoadFromAssemblyPath exclusively loads the requested assembly, ignoring its dependencies; any attempt to iterate through the assembly types fails with a System.Reflection.ReflectionTypeLoadException.

LoaderExceptions 包含 System.IO.FileNotFoundException 的列表.

我很好奇为什么会这样,因为所有必需的文件都在同一个文件夹中.

I'm curious as to why this is the case, since all the required files are in the same folder.

我还尝试将所有 *.dll 文件加载到一个文件夹中,但有些出人意料地失败并显示 System.IO.FileLoadException.

I also tried to load all *.dll files in a folder, but some surprisingly fail with a System.IO.FileLoadException.

我做错了什么?

我不想依赖 .deps 文件(因此排除了 DependencyContext).可能吗?

I wouldn't want to rely on the .deps file (thus ruling out DependencyContext). Is it possible?

推荐答案

嗯,对我有用的是向 Resolving 事件注册一个句柄,并在 LoadFromAssemblyPath 需要依赖项时按需加载所需的程序集.请注意,这是我经过数小时反复试验的解决方案,因此它可能不是最理想的方法.不过,它现在对我有用.这是我的代码:

Well what works for me is to register a handle with the Resolving event and load required assemblies on demand when LoadFromAssemblyPath needs dependencies. Be aware that this my solution from hours of trial and error, so it might not be the most ideal way. It works for me by now though. Here's my code:

    AssemblyLoadContext.Default.Resolving += (context, name) =>
    {
        // avoid loading *.resources dlls, because of: https://github.com/dotnet/coreclr/issues/8416
        if (name.Name.EndsWith("resources"))
        {
            return null;
        }

        var dependencies = DependencyContext.Default.RuntimeLibraries;
        foreach (var library in dependencies)
        {
            if (IsCandidateLibrary(library, name))
            {
                return context.LoadFromAssemblyName(new AssemblyName(library.Name));
            }
        }

        var foundDlls = Directory.GetFileSystemEntries(new FileInfo(<YOUR_PATH_HERE>).FullName, name.Name + ".dll", SearchOption.AllDirectories);
        if (foundDlls.Any())
        {
            return context.LoadFromAssemblyPath(foundDlls[0]);
        }

        return context.LoadFromAssemblyName(name);
    };
}
private static bool IsCandidateLibrary(RuntimeLibrary library, AssemblyName assemblyName)
{
    return (library.Name == (assemblyName.Name))
            || (library.Dependencies.Any(d => d.Name.StartsWith(assemblyName.Name)));
}

IsCandidateLibrary() 位源自于:http://www.michael-whelan.net/replacing-appdomain-in-dotnet-core/

The IsCandidateLibrary() bit originates from there: http://www.michael-whelan.net/replacing-appdomain-in-dotnet-core/

我认为你可以省略这个和整个 DependencyContext 部分,但它充当缓存并避免一遍又一遍地重新加载相同的程序集.所以我保留了它.

I think you could omit this and the whole DependencyContext part, but it acts as a cache and avoids reloading the same assemblies over and over again. So i kept it.

这篇关于.NET Core 中的程序集加载的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆