c# - Autofac:如何加载引用但未直接使用的程序集

标签 c# .net asp.net-web-api dependency-injection autofac

我们已经使用 Autofac for DI 创建了一个 WebApi 解决方案。我们将 autofac 的 Bootstrap 分解为一个单独的项目。这样,我们的 WebApi 项目只引用我们的 Bootstrap 和 Contracts 项目。然后我们的 Bootstrap 项目引用所有其他程序集并将所有内容连接在一起。我喜欢这种关注点分离的设计。

我们可以手动加载我们的程序集,如下所示 - 我们的“AutofacModule”类包含注册每个模块(程序集)的必要信息。

ContainerBuilder builder = new Autofac.ContainerBuilder();
builder.RegisterModule(new Business.AutofacModule());
builder.RegisterModule(new Data.AutofacModule());
builder.RegisterModule(new Services.AutofacModule());
etc...

这可行,但需要对每个程序集进行硬编码。我们正在尝试使其动态化,以便我们可以按如下方式循环遍历所有引用的程序集。

var assemblies = BuildManager.GetReferencedAssemblies().Cast<Assembly>();
foreach (var assembly in assemblies)
{
    builder.RegisterAssemblyModules(assembly);
}

这应该有效但无效。问题是 .Net 确定各种程序集实际上并没有从 Bootstrap 项目中使用,也没有加载它们(试图优化?)。所以我们的一些程序集永远不会加载。

我还尝试了以下循环遍历 bin 目录以查找所有程序集。但是,在编译期间,.Net 不会将未引用的程序集移动到 bin 目录中,因此它们也不存在。

string assemblyPath = System.IO.Path.Combine(
    System.AppDomain.CurrentDomain.BaseDirectory, "bin");
var allAssemblies = new List<Assembly>();
foreach (string dll in Directory.GetFiles(assemblyPath, "*.dll"))
{
    allAssemblies.Add(Assembly.LoadFile(dll));
}

我已将程序集设置为 Copy Local,但这不起作用。我读到了一个 Copy Local 错误并尝试了解决方法,但也没有用。

有没有人能解决这个问题? Autofac 似乎会提供解决方案,但我只找到了他们文档中的待办事项页面: http://autofac.readthedocs.org/en/latest/faq/isolate-autofac.html

下面的两个问题很相似,但是所提出的解决方案都没有克服所需的程序集不在 bin 目录中的事实。

Not all assemblies are being loaded into AppDomain from the bin folder

Loading all referenced assemblies .NET even if not used explicitly in code

最后,我很好奇,这是 Autofac 特有的问题吗?其他DI容器是如何解决这个问题的?我发现 NInject 有类似的问题。 Loading unreferenced dll MVC Ninject

最佳答案

这应该对你有帮助。它获取 bin 文件夹中的所有程序集,从名称 MyModule 开始。

   //builder.RegisterType(typeof(IFoo)).AsImplementedInterfaces();
        ContainerBuilder builder = new ContainerBuilder();

        string[] assemblyScanerPattern = new[] { @"MyModule.*.dll"};

        // Make sure process paths are sane...
        Directory.SetCurrentDirectory(AppDomain.CurrentDomain.BaseDirectory);

        //  begin setup of autofac >>

        // 1. Scan for assemblies containing autofac modules in the bin folder
        List<Assembly> assemblies = new List<Assembly>();
        assemblies.AddRange(
            Directory.EnumerateFiles(Directory.GetCurrentDirectory(), "*.dll", SearchOption.AllDirectories)
                     .Where(filename => assemblyScanerPattern.Any(pattern => Regex.IsMatch(filename, pattern)))
                     .Select(Assembly.LoadFrom)
            );


        foreach (var assembly in assemblies)
        {
            builder.RegisterAssemblyTypes(assembly )
                .AsImplementedInterfaces();
        }
        var container = builder.Build();

这也会加载那些甚至没有被引用的程序集。

关于c# - Autofac:如何加载引用但未直接使用的程序集,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33811015/

相关文章:

C# 在 DateTime 或之前

c# - 配置服务时如何通过依赖注入(inject)在 Azure Function V3 中注入(inject)或使用 IConfiguration

c# - 使用表达式树构造具有未知成员的对象

c# - 在 Botframework V4 中扩展和链接对话框的正确方法?

.net - Bootstrapper 先决条件排序

asp.net-web-api - 如何在 ASP.Net Core (WebAPI) 中基于 HTTP 动词和其他属性以声明方式指定授权策略

asp.net-web-api - 如何在asp.net core Web Api中编写连接字符串?

c# - 如何使用 C# 在 SQL Server 数据库中存储哈希值?

java - JVM设计决策

c# - 无法使用 Unity 将依赖项注入(inject) ASP.NET Web API Controller