在解析公共类时注入内部帮助器类

Mik*_*ike 7 architecture dependency-injection inversion-of-control autofac

我有以下架构,其中引用内部Helper类的公共服务类存在于另一个程序集中:

ApplicationAssembly {
  public class Widget {
    public Widget(ReferencedAssembly.Service service) { ... }
  }
}

ReferencedAssembly {
  public class Service {
    public Service(Helper helper) { ... }
  }
  class Helper { ... }
}
Run Code Online (Sandbox Code Playgroud)

(我意识到我不能在公共类的构造函数的参数中放入内部类 - 我只是想说明我正在追求的IoC模式.)

问题是ApplicationAssembly无法看到ReferencedAssembly.Helper,因此无法在我的IoC容器中注册(在本例中为Autofac).因此,Helper当我尝试解决时无法解决Service.这是我最好的选择?

  • 选项1:HelperService构造函数中删除并在构造函数中明确地将其新建.我不喜欢这个选项,因为它打破了IoC范式.

  • 选项2:使Helper实现成为公共IHelper接口,然后在ReferencedAssembly该寄存器中添加一个公共模块Helper作为IHelper.我不喜欢这个选项,因为它需要ApplicationAssembly知道太多的实现细节Service,如果用户忘记在启动时注册该模块,一切都会中断.

  • 选项3:创建一个公共静态构造函数Service,构建一个专门用于ReferencedAssemblyHelper在其中注册的第二个IoC容器.HelperService构造函数中删除并使用第二个IoC容器在构造函数中解析它.这似乎是我最好的选择,但需要比其他代码更多的"管道"代码.我也不是公共静态构造函数的忠实粉丝.

  • 选项4.将我的架构完全改为其他东西.

Nic*_*rdt 13

使用Autofac注册内部类型的方法是在组件内部包含内部类型的Autofac 模块,并使用容器注册模块.由于模块位于同一个程序集中,因此可以ContainerBuilder使用内部类型进行配置.

我认为最好的选择是使Service实现一个公共接口,然后创建Service你当前内部的类.Autofac将愉快地实例化内部类以提供公共接口.

另一个选项(允许Service对内部类型采用构造函数依赖)是使Service构造函数内部,然后在Service类型注册中使用构造函数查找器:

builder.RegisterType<Service>()
  .FindConstructorsWith(new BindingFlagsConstructorFinder(BindingFlags.NonPublic));
Run Code Online (Sandbox Code Playgroud)

  • 对于任何到达这里并且希望BindingFlagsConstructorFinder是现有类的人,我从DefaultConstructorFinder中取出它并修改它以找到内部构造函数:`FindConstructorsWith(new InternalConstructorFinder);`其中InternalConstructorFinder是:`public class InternalConstructorFinder:IConstructorFinder {public ConstructorInfo [ ] FindConstructors(Type t)=> t.GetTypeInfo().DeclaredConstructors.Where(c =>!c.IsPrivate &&!c.IsPublic).ToArray(); }` (5认同)
  • 它无法解析autofac 3.5中的BindingFlagsConstructorFinder.你知道怎么解决这个问题吗? (3认同)
  • `BindingFlagsConstructorFinder`在Autofac 2.x中(这个答案有点过时了:-)) - 你可以看到原始来源[这里](https://www.symbolsource.org/Public/Metadata/Default/Project/Autofac /2.2.4.900/Release/net-3.5/Autofac/Autofac/Core/Activators/Reflection/BindingFlagsConstructorFinder.cs?ImageName=Autofac). (3认同)