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

C# Autofac:如何加载被引用但未直接使用的程序集,c#,.net,asp.net-web-api,dependency-injection,autofac,C#,.net,Asp.net Web Api,Dependency Injection,Autofac,我们已经使用Autofac for DI创建了一个WebApi解决方案。我们将autofac的自举扩展到一个单独的项目中。这样,我们的WebApi项目只引用我们的引导和契约项目。然后,我们的引导项目引用所有其他程序集并将所有内容连接在一起。我喜欢这种分离关注点的设计 我们可以按如下方式手动加载程序集-其中“AutofacModule”类包含注册每个模块(程序集)所需的信息 这是可行的,但需要对每个部件进行硬编码。我们正试图使其成为动态的,这样我们就可以按如下方式循环所有引用的程序集 var as

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

我们可以按如下方式手动加载程序集-其中“AutofacModule”类包含注册每个模块(程序集)所需的信息

这是可行的,但需要对每个部件进行硬编码。我们正试图使其成为动态的,这样我们就可以按如下方式循环所有引用的程序集

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

以下两个问题是类似的,但没有一个建议的解决方案能够克服所需程序集不在bin目录中的事实

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

//简短回答

您看到了吗:看起来您可以扫描引用的程序集并强制加载它们

//建议(或意见,如果您愿意)


就我个人而言,我不会加载那些不会仅仅为了能够有一个单独的项目进行引导而使用的程序集。我不认为在它自己的项目中使用它有什么好处。请记住,DI就是这样,您正在注入“那个”项目的依赖项。每个项目都可以有自己的依赖项,关注点的分离来自引导类,而不是它在自己的项目中。如果您需要将您的业务逻辑项目分解成一个nuget包,而您公司的其他项目也将使用该包,那么您不希望他们也必须下载DI项目包,而DI项目包现在需要的是它可能永远不会使用的其他包。如果您的依赖项包含在需要它们的项目中,那么它将变得模块化和可扩展。答案的这一部分当然有争议,但至少应该予以考虑

这应该对你有帮助。它接受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();
//builder.RegisterType(typeof(IFoo)).AsImplementedInterfaces();
ContainerBuilder=新的ContainerBuilder();
string[]assemblyScanerPattern=new[]{@“MyModule.*.dll”};
//确保进程路径是合理的。。。
目录.SetCurrentDirectory(AppDomain.CurrentDomain.BaseDirectory);
//开始设置自动传真>>
// 1. 在bin文件夹中扫描包含autofac模块的程序集
列表程序集=新列表();
assemblies.AddRange(
枚举文件(Directory.GetCurrentDirectory(),“*.dll”,SearchOption.AllDirectories)
.Where(文件名=>assemblyScanerPattern.Any(模式=>Regex.IsMatch(文件名,模式)))
.Select(Assembly.LoadFrom)
);
foreach(程序集中的变量程序集)
{
builder.RegisterAssemblyTypes(程序集)
.a实现接口();
}
var container=builder.Build();

这将加载那些甚至未被引用的程序集

如果解决方案中有多个项目,每个项目都有自己的IoC容器类,请使用以下命令加载所有程序集,然后在该程序集中注册每个模块

var assemblies = Directory.EnumerateFiles(AppDomain.CurrentDomain.BaseDirectory, "*.dll", SearchOption.TopDirectoryOnly)
   .Where(filePath => Path.GetFileName(filePath).StartsWith("your name space"))
   .Select(Assembly.LoadFrom);

var builder = new ContainerBuilder();

builder.RegisterAssemblyTypes(assemblies.ToArray())
   .Where(t => typeof(ITransientDependency).IsAssignableFrom(t))
   .AsImplementedInterfaces();
这是ContainerBuilder的扩展方法

public static class ContainerBuilderExtensions
{
    public static void ScanAssembly(this ContainerBuilder builder, string searchPattern = "SolutionName.*.dll")
    {
        var path = AppDomain.CurrentDomain.BaseDirectory;
        foreach (var assembly in Directory.GetFiles(path, searchPattern).Select(Assembly.LoadFrom))
        {
            builder.RegisterAssemblyModules(assembly);
        }
    }
}
可以在ContainerBuilder的实例上调用上述内容,如下所示:

builder.ScanAssembly()

我正在使用Autofac在运行时使用“.RegisterAssemblyModules”方法从程序集动态加载模块,它的工作方式很有魅力。唯一的要求是,任何应该加载的程序集都必须以特定的后缀(对于目录.GetFiles)结束,如“*.Plugin.dll”。谢谢。我们的问题是引导项目引用但不直接使用我们的许多程序集。所以我认为编译器认为它们不是必需的,所以它从不将它们移动到bin目录中。因此,我没有要加载的内容。所有“*.Plugin.dll”文件都会通过生成后操作移动到\bin文件夹,该操作正在为发布版收集程序集。builder.RegisterAssemblyTypes接受程序集数组,因为每个都不是必需的
public static class ContainerBuilderExtensions
{
    public static void ScanAssembly(this ContainerBuilder builder, string searchPattern = "SolutionName.*.dll")
    {
        var path = AppDomain.CurrentDomain.BaseDirectory;
        foreach (var assembly in Directory.GetFiles(path, searchPattern).Select(Assembly.LoadFrom))
        {
            builder.RegisterAssemblyModules(assembly);
        }
    }
}
builder.ScanAssembly()