现在,我已经阅读了Mark Seemann的书(至少是这个讨论的相关部分),我明白为什么一个服务定位器是坏的,为什么在组合根(在我的情况下的服务起点)处理这个是好的 – 一般情况.
但是,我不明白的是,这可以适用于每一种情况.我可以看到,在您可以在应用程序开始时编写整个根源的情况下,或者像框架中的每个请求使用IoC引擎的类似MVC的情况下,它将是完美的.然而,对于长期运行的服务,我想象在最好的情况下效率会很低,在某些情况下,不可能在前面创建所有的对象.我无法想象能够编写一个非常简单的服务,它可以获得所有可能需要的对象,而且随着生活的发展,也不需要创建新的对象.
现在,这不足以引诱我到黑暗的一面,并牺牲隐藏的依赖,像一个服务定位器会让我做的.但在这里做什么是正确的事情?如果我有一个CallHandlerService,需要创建响应每个来电(因为它使用昂贵的非托管资源,例如),我该如何去做?
组成根只是一点点的服务定位器?
最后一部分不严重,但我仍然希望知道如何正确地解决这个问题.
解决方法
>如何管理范围
>避免前面创建所有可能的依赖项
>仅创建所需的依赖关系
>如何管理生命周期
保持对已创建的依赖关系的引用
>如果有可能,重用依赖项
>尽快清理它们
如何管理范围
您可以定义几个专业抽象工厂的接口或实现,每个工厂都将仅限于管理其自己的特殊类型的依赖关系.例如:一个用于数据库相关的依赖关系,另一个与SIP相关.那么你可以自己注入工厂,而不是依赖关系,并从中检索依赖关系.
听起来不像服务定位器吗?是的,但它不是服务定位器.您可以在Mark Seemann blog: Abstract Factory or Service Locator?阅读更多.
如果抽象工厂可以,请查看Ninject.Extensions.Factory根据您的IKernel配置自动创建它们
如何管理生命周期
如果你要运行你的服务24-7,这是比较复杂和重要的部分.在这里我可以给你几个实用的建议:
>对于这种服务,外部依赖方(即数据库,服务)的失败是常规的,而不是例外>不要将自己的依赖关系保留在旨在执行性能或重用的代码中>不要使用复杂的生命周期(例如Ninject的命名范围)>尽快发布依赖关系.配置Ninject为您管理它们.考虑超时的依赖关系,重新创建新的实例>可能是长时间运行的任务,创建单独的内核实例,并确保您之后处理它们