如何在 dotnet core 中动态加载程序集 [英] How to dynamically load assemblies in dotnet core

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

问题描述

我正在构建一个 Web 应用程序,我希望在其中单独关注,即在不同项目中具有抽象和实现.

I'm building a web application, where I would like separate concerns, i.e. having abstractions and implementations in different projects.

为了实现这一点,我试图实现一个组合根概念,其中所有实现都必须有一个 ICompositionRootComposer 的实例来注册服务、类型等.

To achieve this, I've tried to implement a composition root concept, where all implementation must have an instance of ICompositionRootComposer to register services, types etc.

public interface ICompositionRootComposer
{
    void Compose(ICompositionConfigurator configurator);
}

在构建层次结构中直接引用的项目中,会调用 ICompositionRootComposer 的实现,并且在底层 IoC 容器中正确注册服务.

In projects that are referred directly in the build hierarchy, implementations of ICompositionRootComposer are called, and services are registered correct in the underlying IoC container.

当我尝试在项目中注册服务时出现问题,我在其中设置了一个后期构建任务,将构建的 dll 复制到 Web 项目的调试文件夹:

The problem arises when I'm trying to register services in a project, where I've set up a post build task that copies the built dll to the web project's debug folder:

cp -R $(TargetDir)"assembly and symbol name"* $(SolutionDir)src/"webproject path"/bin/Debug/netcoreapp1.1

我正在加载程序集:(灵感:如何加载位于 .net core 控制台应用程序文件夹中的程序集)

I'm loading the assembly with: (Inspiration: How to load assemblies located in a folder in .net core console app)

internal class AssemblyLoader : AssemblyLoadContext
{
    private string folderPath;

    internal AssemblyLoader(string folderPath)
    {
        this.folderPath = Path.GetDirectoryName(folderPath);
    }

    internal Assembly Load(string filePath)
    {
        FileInfo fileInfo = new FileInfo(filePath);
        AssemblyName assemblyName = new AssemblyName(fileInfo.Name.Replace(fileInfo.Extension, string.Empty));

        return this.Load(assemblyName);
    }

    protected override Assembly Load(AssemblyName assemblyName)
    {
        var dependencyContext = DependencyContext.Default;
        var ressource = dependencyContext.CompileLibraries.FirstOrDefault(r => r.Name.Contains(assemblyName.Name));

        if(ressource != null)
        {
            return Assembly.Load(new AssemblyName(ressource.Name));
        }

        var fileInfo = this.LoadFileInfo(assemblyName.Name);
        if(File.Exists(fileInfo.FullName))
        {
            Assembly assembly = null;
            if(this.TryGetAssemblyFromAssemblyName(assemblyName, out assembly))
            {
                return assembly;
            }
            return this.LoadFromAssemblyPath(fileInfo.FullName);
        }

        return Assembly.Load(assemblyName);
    }

    private FileInfo LoadFileInfo(string assemblyName)
    {
        string fullPath = Path.Combine(this.folderPath, $"{assemblyName}.dll");

        return new FileInfo(fullPath);
    }

    private bool TryGetAssemblyFromAssemblyName(AssemblyName assemblyName, out Assembly assembly)
    {
        try
        {
            assembly = Default.LoadFromAssemblyName(assemblyName);
            return true;
        }
        catch
        {
            assembly = null;
            return false;
        }
    }
}

有了这个,我就可以加载程序集并调用项目 ICompositionRootComposer 实现.

With this I'm able to load the assembly and call the projects ICompositionRootComposer implementation.

但问题是它似乎无法识别我的任何类型.

But the problem is that it doesn't seem to recognize any of my types.

调用我的配置器时

configurator.RegisterTransiantService<IFoo, Foo>();

它应该在 IoC 中注册 IFoo 和 Foo.
但是在调试时,我无法获取类型的信息,即通过 Visual Studio Code 调试控制台中的 typeof(Foo).

it should register IFoo and Foo in the IoC.
But when debugging I'm not able to get info of the types, i.e via typeof(Foo) in the debug console in Visual Studio Code.

推荐答案

我找到了解决问题的方法.

I found a solution to my problem.

事实证明,我将 PreserveCompilationContext 属性设置为 true,这就是调试器不会注册我手动复制的程序集的原因.当我从 Web 项目 csproj 文件中删除该属性时,一切正常.

It turned out, that I had the property PreserveCompilationContext set to true, and that's why the debugger wouldn't register my manually copied assembly. When I removed the property from the web project csproj file, everything worked.

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

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