长时间运行的Windows服务中的依赖注入 - 组合根本正确的想法?

Run*_*sen 9 c# windows-services dependency-injection ninject

我正在编写一个Windows服务(如果一切按计划进行)将一次运行几个月.在服务的整个生命周期中,它将维护几个WCF服务(用于与其他本地应用程序通信的命名管道),它将运行嵌入式数据存储(可能是RavenDB,这或多或少与此问题无关),并且它将使用一些第三方软件维护SIP服务(VoIP功能).我面临的一些挑战意味着必须对事件做出反应并创建一些新的业务对象来处理这些事件所代表的内容.

现在,我已经阅读了Mark Seemann的书(至少是本次讨论的相关部分),我理解为什么服务定位器不好,为什么在组合根(在我的情况下是服务起点)处理这个问题是好的 - 一般情况.

但是,我不明白这是如何适用于所有情况的.我看到在应用程序启动时可以组成完整根目录的情况下,或者像MVC那样,框架中每个请求都使用IoC引擎的情况下,它会如何完美.但是,对于长期运行的服务,我认为在最好的情况下效率很低,而且在某些情况下不可能预先创建所有对象.我无法想象能够编写一个非平凡的服务来获取它可能需要的所有对象,并且永远不需要在生活中创建新的对象.

现在,这还不足以引诱我走向黑暗面并承担隐藏的依赖关系,就像服务定位器会让我做的那样.但在这里做什么是正确的?如果我有一个CallHandlerService需要创建以响应每个传入的调用(因为它使用昂贵的非托管资源),我该如何去做呢?

组合根+只是一点点的服务定位器?

最后一部分并不严肃,但我仍然想知道如何妥善解决这个问题.

Aki*_*kim 15

有可能将问题分为两个:

  • 如何管理范围
    • 避免在前面创建所有可能的依赖项
    • 创建所需的依赖项
  • 如何管理一生
    • 保持对已创建的依赖项的引用
    • 如果可能,重用依赖项
    • 尽快清理它们

如何管理范围

您可以定义几个专门的抽象工厂的接口或实现,每个都将限制为管理其自己的特殊依赖类型.例如:一个用于数据库相关的依赖项,另一个用于SIP相关.然后,您可以自己注入工厂,而不是依赖项,并从中检索依赖项.

这听起来不像服务定位器吗?是的,但它不是服务定位器.您可以在Mark Seemann博客上阅读更多相关内容:抽象工厂或服务定位器?.

如果抽象工厂没问题,请查看Ninject.Extensions.Factory,根据您的IKernel配置自动创建它们

如何管理一生

如果您打算以24-7运行您的服务,这是更复杂和重要的部分.在这里,我只能给你一些实用的建议:

  • 对于这种类型的服务,外部依赖方(即数据库,服务)的故障是常规的,而不是例外
  • 不要在代码中保留对依赖项的任何引用,以实现性能或重用
  • 不要使用复杂的生命周期(例如Ninject的命名范围)
  • 尽快释放依赖关系.配置Ninject为您管理它们.
  • 考虑依赖项的超时,重新创建新实例
  • 可以用于长时间运行的任务,创建单独的实例Kernel,并确保之后已经处理它们