Law*_*eld 37 c# singleton dependency-injection dependency-management service-locator
我目前正在权衡DI和SL之间的优缺点.但是,我发现自己处于以下问题22中,这意味着我应该只使用SL作为一切,并且只在每个类中注入一个IoC容器.
DI Catch 22:
一些依赖项,如Log4Net,根本不适合DI.我称之为元依赖关系并认为它们对调用代码应该是不透明的.我的理由是,如果一个简单的类'D'最初是在没有记录的情况下实现的,然后增长到需要记录,那么依赖类'A','B'和'C'现在必须以某种方式获得这种依赖并将其从'A'到'D'(假设'A'组成'B','B'组成'C',依此类推).我们现在已经进行了重要的代码更改,因为我们需要登录一个类.
因此,我们需要一种不透明的机制来获取元依赖性.我想到了两个:Singleton和SL.前者具有已知的局限性,主要是关于刚性范围的能力:最好的是Singleton将使用存储在应用程序范围内的抽象工厂(即在静态变量中).这允许一些灵活性,但并不完美.
更好的解决方案是将IoC容器注入此类,然后使用该类中的SL从容器中解析这些元依赖关系.
因此,捕获22:因为类现在正在注入IoC容器,那么为什么不使用它来解析所有其他依赖项呢?
我非常感谢你的想法:)
jas*_*son 59
因为该类现在正在注入IoC容器,那么为什么不使用它来解析所有其他依赖项呢?
使用服务定位器模式完全打败了依赖注入的一个主要点.依赖注入的关键是使依赖关系显式化.一旦你通过不在构造函数中使它们成为显式参数来隐藏这些依赖项,就不再需要完全成熟的依赖注入了.
这些都是名为Foo
(设置为Johnny Cash歌曲主题)的类的构造函数:
错误:
public Foo() {
this.bar = new Bar();
}
Run Code Online (Sandbox Code Playgroud)
错误:
public Foo() {
this.bar = ServiceLocator.Resolve<Bar>();
}
Run Code Online (Sandbox Code Playgroud)
错误:
public Foo(ServiceLocator locator) {
this.bar = locator.Resolve<Bar>();
}
Run Code Online (Sandbox Code Playgroud)
对:
public Foo(Bar bar) {
this.bar = bar;
}
Run Code Online (Sandbox Code Playgroud)
只有后者才会依赖于Bar
显式.
对于日志记录,有一种正确的方法可以实现它,而不会渗透到您的域代码中(它不应该,但如果确实如此,则使用依赖注入时段).令人惊讶的是,IoC容器可以帮助解决这个问题.从这里开始.
服务定位器是一种反模式,其原因在http://blog.ploeh.dk/2010/02/03/ServiceLocatorIsAnAntiPattern.aspx中有详细描述.在日志记录方面,您可以像其他任何一样将其视为依赖项,并通过构造函数或属性注入注入抽象.
与log4net唯一的区别是它需要使用该服务的调用者类型. 使用Ninject(或其他一些容器)如何找出请求服务的类型?描述了如何解决这个问题(它使用Ninject,但适用于任何IoC容器).
或者,您可以将日志记录视为一个交叉问题,这不适合与业务逻辑代码混合使用,在这种情况下,您可以使用由许多IoC容器提供的拦截. http://msdn.microsoft.com/en-us/library/ff647107.aspx描述了使用Unity进行拦截.
小智 5
我的意见是,这取决于.有时一个更好,有时另一个.但我会说通常我更喜欢DI.原因很少.
当以某种方式将依赖注入组件时,它可以被视为其接口的一部分.因此,组件的用户更容易提供这种依赖,因为它们是可见的.在注入SL或静态SL的情况下,隐藏了依赖关系并且组件的使用有点困难.
注入的依赖对于单元测试更好,因为您可以简单地模拟它们.在SL的情况下,您必须再次设置Locator + mock依赖项.所以这是更多的工作.
归档时间: |
|
查看次数: |
37099 次 |
最近记录: |