如何在.NET中使用解决方案获取所有程序集?

时间:2018-05-13 20:37:43

标签: .net .net-assembly layer n-tier-architecture

我有一个典型的3层.NET应用程序。

域层不会引用其他项目。

数据访问层引用域层并实现一些存储库。

Web视图层使用域层服务并控制Autofac(IOC容器)。

域和数据访问层实现Autofac模块。这意味着,从Web视图层,我可以扫描所有程序集并使用Autofac注册它们,以便提供依赖注入。

我不希望我的Web视图层知道或关心使用哪个数据访问层,因此我不想包含对它的引用。但是,如果我没有引用数据访问层,则查找程序集的扫描将不会进行检索。

以下是在Web视图层中调用的启动方法:

private static void RegisterAutofacAssemblyModules(ContainerBuilder builder)
    {
        IEnumerable<Assembly> assemblies = AppDomain.CurrentDomain.GetAssemblies().Where(x => x.FullName.Contains("Boutique"));

        if (HostingEnvironment.InClientBuildManager)
        {
            assemblies = assemblies.Union(BuildManager.GetReferencedAssemblies().Cast<Assembly>()).Distinct();
        }

        builder.RegisterAssemblyModules(assemblies.ToArray());
    }

我添加了.Where()以希望提高性能,因为必须扫描更少的程序集。 (不确定这是否属实)。

如果我引用数据访问层(在Web视图层中),此代码可以正常工作。但我不希望Web视图层引用数据访问层。那么如何扫描程序集以确保包含数据访问层?如果可能的话,我想在解决方案中获得所有组件。

1 个答案:

答案 0 :(得分:1)

在我看来,您可能错过了一个Cross Cutting层来处理您的IoC容器注册。

创建一个名为CrossCutting.IoC的新类项目并将所有Autofac注册移动到它,除了Web视图层注册外,这些注册将由Web层本身处理。

因此,Web Layer将引用IoC层,并且不再需要对Data层的引用。 IoC层将引用其他所有项目。

我使用SimpleInjector,因此我从未在Autofac中实现此功能,但在快速搜索之后,您似乎需要使用此Modules中所述的answer。如果您遵循该答案的建议并为每个层创建一个模块,那么您可以使用RegisterAssemblyModules并立即注册所有模块。

修改

我刚刚在一个WebAPI项目中对此进行了测试,其中包含与您加CrossCutting.IoC相同的图层,并且它有效。根据{{​​3}},您甚至不必使用AppDomain,只需使用BuildManager

protected void Application_Start()
{
    var builder = new ContainerBuilder();

    var config = GlobalConfiguration.Configuration;

    builder.RegisterApiControllers(Assembly.GetExecutingAssembly());
    builder.RegisterWebApiFilterProvider(config);
    builder.RegisterWebApiModelBinderProvider();

    // Automatically scan and register all modules found in referenced assemblies
    var assemblies = BuildManager.GetReferencedAssemblies().Cast<Assembly>().ToArray();
    builder.RegisterAssemblyModules(assemblies);

    var container = builder.Build();
    config.DependencyResolver = new AutofacWebApiDependencyResolver(container);
}

我不会为运行时扫描配置它,我认为这是一种风险,我更喜欢明确它,所以如果你愿意,只需用RegisterModule调用替换自动扫描部分每个模块:

builder.RegisterModule<CrossCuttingModule>();
builder.RegisterModule<DomainModule>();
// etc...