【问题标题】:Manually implementing IoC with a Windows Service使用 Windows 服务手动实现 IoC
【发布时间】:2011-07-26 01:28:05
【问题描述】:

我是 IoC 的新手,因此一直在关注 Jeffery Palermo 在他的帖子http://jeffreypalermo.com/blog/the-onion-architecture-part-1/ 和他的书中提供的示例https://github.com/jeffreypalermo/mvc2inaction/tree/master/manuscript/Chapter23

最需要注意的是,我没有使用预滚动的 IoC 容器,主要是因为我想了解所有活动部件。

但是,我正在创建一个 Windows 服务而不是一个 ASP.NET MVC webapp,所以我在启动部分几乎没有陷入困境。具体来说,在 web.config 中,他在基础设施项目中注册了一个 IHttpModule 实现作为启动模块,然后使用构建后事件将必要的 dll 复制到网站目录中,以绕过对 Web 项目本身的直接依赖。

我认为我在真正的 Windows 服务中没有这种奢侈,那么我应该如何实现类似的东西,我应该有一个同时依赖于基础结构和核心的小型启动项目,还是有另一种方法绕过windows服务的编译时限制?

提前致谢。

【问题讨论】:

  • 特别是如果您是 IoC 的新手,我建议您使用众所周知的(并且经过测试!)IoC 容器。自己编写一个是一种高尚的方法,但从长远来看,你会浪费每个程序员已经投入的容器的时间。关于您的问题:引用 IoC 框架有什么问题?
  • @Zebi,参考问题不是关于引用 IoC 框架,而是关于直接引用基础结构 dll。 IoC 的重点似乎是消除这些传递依赖。 Web 项目的启动似乎利用了一个漏洞,即 web.config 可用于配置对基础设施层的调用,这对我来说有点欺骗,因为在桌面应用程序或服务中这样做您将无法使用相同的技术,并且必须直接从您的应用程序或 UI 项目中引用基础架构 dll,从而违背了 IoC 的目的。
  • IoC 容器的目的不是管理您的程序集引用。目的是管理类的依赖关系。 IoC 模式本身与程序集毫无关系。
  • @Zebi,但引用不是暗示依赖吗?
  • 我添加了一个答案来澄清。如果这对您有所解释,请发表评论。

标签: c# windows-services inversion-of-control


【解决方案1】:

根据这个问题的标签 (c#),我假设您将通过从 ServiceBase 派生来实现 Windows 服务。如果是这样,OnStart 方法将是您的 Composition Root - 这是您组成应用程序对象图的地方。组合对象图后,组合结束,组合对象图接管。

在 OnStop 中,您可以再次停用对象图。

没有什么能阻止您在单独的程序集中实现已解析对象图的各种组件。这就是我会做的。

【讨论】:

  • 今天我有空时必须进一步挖掘你的答案(这是我的副项目)但是看看我是否理解,你是否建议将引导程序拉到它自己的大会,还是我完全错过了那里的重点?
  • 就个人而言,我会将引导程序保留在包含 ServiceBase 派生类的程序集中,并将其他所有内容放在一个或多个单独的程序集中。
【解决方案2】:

我认为您误解了 IoC 框架的作用。

回答你的问题

但是引用不是暗示依赖吗?

是的,但在另一个层面上。 IoC 是关于类之间的依赖关系。 而不是在你的类中使用new Something(),你提供了一个需要所有依赖接口的构造函数。这样,类就无法控制传递给它的实现。这是控制反转。 IoC 容器只是帮助以一种很好的方式管理依赖项的辅助工具。

假设你有一个ICustomerNotificationService 接口,其实现类似于

public class MailNotificationService : INotificationService
{
    IMailerService _mailer;
    ICustomerRepository _customerRepo;
    IOrderRepository _orderRepo;

    public MailNotificationService(IMailerService mailer, 
                                   ICustomerRepository customerRepo, 
                                   IOrderRepository oderRepo)
    {
        // set fields...
    }

    public void Notify(int customerId, int productId)
    {
        // load customer and order, format mail and send.
    }
}

因此,如果您的应用程序请求ICustomerNotificationServcie 的实例,容器会确定要采用哪些具体实现,并尝试满足所请求类的所有依赖项。

优点是您可以轻松地在引导逻辑中配置所有依赖项,并且能够非常轻松地更改应用程序的行为。

例如,在测试时,您使用IMailerService 实现启动应用程序,该实现将邮件写入文件,并且在生产模式下,连接了真正的邮件服务。如果您在构造函数中新建了一个 MailerService 而不是将其作为参数,则这是不可能的。

一个好的 IoC 容器可以处理更多,比如生命周期管理、单例、扫描程序集以查找要注册的类型等等。例如,我们将整个插件系统基于Structure Map。

您可能想看看this blog article 及其second part。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2012-11-24
    • 2016-04-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-02-06
    • 1970-01-01
    • 2021-05-11
    相关资源
    最近更新 更多