在.NET Core中加载程序集

时间:2016-12-01 10:46:00

标签: c# reflection .net-core

使用VS2017 RC,.NET Core

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

我正在使用LoadFromAssemblyPath

我意识到System.Reflection.ReflectionTypeLoadException只是加载所请求的程序集,忽略它的依赖关系;任何迭代装配类型的尝试都失败了LoaderExceptions

System.IO.FileNotFoundException包含System.IO.FileLoadException的列表。

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

我还尝试将所有* .dll文件加载到一个文件夹中,但有些令人惊讶地失败了"react-router": "^3.0.0"

我做错了什么?

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

2 个答案:

答案 0 :(得分:8)

对我来说有用的是在LoadFromAssemblyPath需要依赖项时,使用Resolving事件注册句柄并按需加载所需的程序集。请注意这是我的解决方案,从几个小时的试验和错误,所以它可能不是最理想的方式。它现在适用于我。这是我的代码:

    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/

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

答案 1 :(得分:3)

.Net Core 3.0+中有一个很大的增强,如下所示,发生了AssemblyLoadContext.Default.Resolving事件,所有依赖关系都将被解析和加载:

 AssemblyLoadContext.Default.Resolving += (context, name) => {
                string assemblyPath = $"{pluginFolder}\\{name.Name}.dll";                
                if (assemblyPath != null)   
                    return context.LoadFromAssemblyPath(assemblyPath);     
                return null;
            };

记住要定义变量pluginFolder

解决方案2

您可以使用AssemblyDependencyResolver类并解决依赖关系,包括.deps.json中的依赖关系:

  var resolver = new AssemblyDependencyResolver(pluginPath);            

  AssemblyLoadContext.Default.Resolving += (context, name) => {

                string assemblyPath = resolver.ResolveAssemblyToPath(name);               
                if (assemblyPath != null)   
                    return context.LoadFromAssemblyPath(assemblyPath);     
                return null;
            };