c# - 如何在 dotnet core 中动态加载程序集

标签 c# asp.net-core .net-core

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

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

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

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

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

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

我正在加载程序集:(灵感: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 实现。

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

当调用我的配置器时

configurator.RegisterTransiantService<IFoo, Foo>();

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

最佳答案

死灵法术。


您可以为旧的 Assembly.LoadFile 创建一个包装类来执行此操作。

这还有一个额外的好处,即您可以通过在旧代码库中应用搜索和替换更改来保持与 dotnet-none-core 的向后兼容。

namespace System.Reflection
{
    public class Assembly2
    {
        public static System.Reflection.Assembly LoadFile(string path)
        {
            System.Reflection.Assembly assembly = null;
            
#if NET_CORE
            // Requires nuget - System.Runtime.Loader
            assembly = System.Runtime.Loader.AssemblyLoadContext.Default.LoadFromAssemblyPath(path);
#else
            assembly = System.Reflection. Assembly.LoadFile(path);
#endif 
            return assembly;
        }
    }
}

您需要通过 NuGet 添加 System.Runtime.Loader

关于c# - 如何在 dotnet core 中动态加载程序集,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43353999/

相关文章:

c# - 使用 CaSTLe Windsor 在基类中注入(inject)原始属性

c# - 从 Entity Framework 6 + MySQL 的代码设置数据库创建/迁移

c# - EF-Core 尝试插入已经存在的关系数据

visual-studio-2015 - 在 nuget/.NET Core 时代使用多种解决方案和文件引用

c# - 将枚举映射到使用 ConvertUsingEnumMapping 定义两次的值时出错

c# - &lt;script&gt;...&lt;/script&gt; 在转发器控制代码中未显示在页面呈现的源代码中

c# - .Net 应用程序内存管理

asp.net-core - nlog中不同环境的Base Directory路径

.net-core - 在树莓派上用.Net Core C#录制的音频保存到Wav文件

c# - 在 ASP.NET Core 项目中使用没有 Entity Framework 的 SQLite 数据库