我最终使用了 Wiktor 的方法,但略有不同,因为我无法及时进入 .NET 4.5 以使我的解决方案生效。所以我无法使用自动注册。
相反,我首先使用加载了任何 xml 配置
container.LoadConfiguration();
重要的是要认识到,在许多情况下,有一个抽象的默认实现,使用了 %90+ 的时间。事实上,通常情况下,总是使用默认值,除非在模拟依赖项进行测试时。因此,让注册默认值变得容易是一个好主意。
我的团队有一个约定,默认值由包含默认值的程序集中的注册类注册。注册类可以通过反射发现。通常,接口或抽象类将位于不同的契约程序集中。
注册总是包含在保护子句中:
if (!container.IsRegistered<IMyService>())
{
container.RegisterType<IMyService, MyService>()
}
我还向 IUnityContainer 添加了一个扩展方法,以使我的开发人员不那么冗长
public static IUnityContainer RegisterIfUnRegistered<TAbstraction, TImplementation>(
this IUnityContainer container) where TImplementation : TAbstraction
{
if (!container.IsRegistered <TAbstraction>())
{
container.RegisterType<TAbstraction, TImplementation>();
}
return container; //Make it fluent
}
对此有各种重载,采用命名注册和工厂注册等。
现在,99% 的时间都会发现默认实现,但可以按照 Wiktor 的建议在 xml 中覆盖它们。
这可能看起来有点像烟雾和镜子。自动注册通常确实有这种感觉。多年来,它一直在 Castle Windsor 和其他依赖容器框架中可用。遗憾的是,我们不得不等待 11 年才能在 Microsoft 的产品中使用它。嗯。我跑题了。
只要遵循在实现程序集中注册默认值的约定,单元测试和调试注册就变得非常容易。
但是请记住,通过反映程序集或直接调用注册类来执行注册的代码应该非常接近可执行文件中的 main 方法。这是你的作文根。有关依赖注入的更多信息,请参阅 Mark Seeman 的博客。他写了关于 DI 的书。我强烈推荐这个。