2

我一直在与Ninject一起使用依赖注入来实现应用程序。我觉得我对这些概念有非常透彻的理解,并且非常喜欢应用程序使用DI实现的松耦合和可测试架构。然而,我正在努力应对一种特定类型的服务,并且正在寻找我是否做错了事或者其他人是否碰到过同样的事情。不依赖服务的DI服务

基本上,我最终得到了一些服务/类(一个很小的数字),根据它们没有其他服务。正因为如此,即使该类在应用程序中执行了有用的角色,但它也不会被实例化,即使它是必需的。举个例子,假设我有一个IMonkeyRepository服务和一个IMonkeyPopulator服务。假设IMonkeyPopulator服务确实没有公共API,并且其唯一的责任(遵循单一责任原则)是发现网络上的猴子并使用它们填充IMonkeyRepository。该服务取决于IMonkeyRepository以及其他一些服务来处理其与网络的交互(例如,端口和地址的配置数据)。但是,IMonkeyPopulator没有公共的API,它只是一个空的接口。

这是一个糟糕的设计或某种我错过的代码味道?我明显可以将这个功能移入存储库本身,但这对我来说似乎违反了SRP(存储库具有有用的访问功能等,实际上可能由多个服务填充)。我已经考虑或尝试但不满意的一些方法是:

  1. 使服务具有一个公共方法,例如Start,必须调用它才能开始工作。这有一个缺点,即需要确定系统中的某个位置来进行此调用。
  2. 将服务绑定到我创建Ninject内核时实例化的常量。这要求我明白,没有人依赖这项服务,因此必须专门处理,这似乎是错误的。
  3. 将一些成员添加到服务中,并在我的应用程序中的某个位置创建一个读取这些值(例如服务状态等)的GUI。显然,不得不为我的应用程序添加一个GUI,因为这个原因是非常愚蠢的(尽管有时用于调试等)。

任何想法或指导?

回答

3

你说IMonkeyPopulator取决于IMonkeyRepository,但它似乎应该是另一种方式?这听起来像你的IMonkeyRepository取决于,因此可能需要注入,IMonkeyPopulator。如果你还注入了其他一些服务,但在内部,IMonkeyRepository可能会告诉IMonkeyPopulator“启动”,以便存储库中实际存在某些内容。我可能会误解这个问题,但是......也许我不应该在这么多地瞎搞:/

+0

有趣的,但我*认为*这种做法会违反单一责任原则。假如我有多个populator,我将不得不将它们全部注入到资源库(并启动它们)。现在,存储库类必须随时更改新的populator,以及何时访问存储库中项目的方式需要更改。更改类的多个原因表示违反了SRP。话虽如此,我认为这种方法可以和我想到的一样好。 – StellarEleven

+1

在这种情况下,我会注入一个像IMonkeyPopulatorAggregate这样的对象,并从存储库中调用它的populate()方法。如果我需要添加更多的populator,仓库代码根本不会改变。话虽如此,但根据我的经验,对于每一种可能的偶然事件而不是现有的具体问题(也许你提到的情况是你的具体问题 - 我不知道)的计划就像寻找兔子洞的底部。最后,一旦你确实了解了具体的规则/原则/模式/哲学/风格,保留违反它的权利。 – Quanta

3

因此你的IMonkeyPopulator是某种ActiveObject,它在后台侦听一个tcp连接并将该数据写入存储库。我会从应用程序的角度来说,活动对象必须启动和停止,因为您不想在构造函数中启动tcp连接。所以,你可以使用绑定的OnActivationOnDeactivation方法来启动和停止,像这样的服务:

This.Bind<IPopulatorService>().To<>().OnActivation((c, i) => i.Start()).OnDeactivation((c, i) => i.Stop()) 

但还是有人在你的应用程序,以获取/获得订单IPopulatorService得到它在你的应用实例。为了实现这个目的,我通常在这里使用引导程序模式http://www.appccelerate.com/bootstrapper.html

+0

为什么你会说我不想在构造函数中启动TCP连接? – StellarEleven

+0

我练习TDD很多,如果你的对象在创建时很容易构造并且非活动 –