我有以下架构,其中引用内部Helper类的公共服务类存在于另一个程序集中:
ApplicationAssembly {
public class Widget {
public Widget(ReferencedAssembly.Service service) { ... }
}
}
ReferencedAssembly {
public class Service {
public Service(Helper helper) { ... }
}
class Helper { ... }
}
(我意识到我不能在公共类的构造函数的参数中加入内部类 - 我只是想说明我正在追求的IoC模式。)
问题是ApplicationAssembly
无法看到ReferencedAssembly.Helper
,因此无法在我的IoC容器中注册(在本例中为Autofac)。因此,当我尝试解析Helper
时无法解析Service
。我最好的选择是什么?
选项1:从Helper
的构造函数中删除Service
并在构造函数中明确地将其新建。我不喜欢这个选项,因为它打破了IoC范式。
选项2:让Helper
实施公开IHelper
界面,然后在ReferencedAssembly
中添加一个将Helper
注册为IHelper
的公共模块。我不喜欢这个选项,因为它需要ApplicationAssembly
知道关于Service
的太多实现细节,如果用户忘记在启动时注册该模块,那么一切都会中断。
选项3:在Service
上创建一个公共静态构造函数,专门为ReferencedAssembly
构建第二个IoC容器,并在其中注册Helper
。从Helper
的构造函数中删除Service
,并使用第二个IoC容器在构造函数中解析它。这似乎是我最好的选择,但需要比其他代码更多的“管道”代码。我也不是公共静态构造函数的忠实粉丝。
选项4.将我的架构改为其他内容。
答案 0 :(得分:12)
使用Autofac注册内部类型的方法是在程序集内部包含Autofac Module和内部类型,并使用容器注册模块。由于模块位于同一个程序集中,因此可以使用内部类型配置ContainerBuilder
。
我认为最好的选择是让Service
实现一个公共接口,然后创建当前内部的Service
类。 Autofac将愉快地实例化一个内部类以提供公共接口。
另一个选项(允许Service
对内部类型采用构造函数依赖)是使Service
的构造函数内部,然后在Service
中使用构造函数查找器类型注册:
builder.RegisterType<Service>()
.FindConstructorsWith(new BindingFlagsConstructorFinder(BindingFlags.NonPublic));