我有一个典型的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视图层引用数据访问层。那么如何扫描程序集以确保包含数据访问层?如果可能的话,我想在解决方案中获得所有组件。
答案 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...