2010-02-11 67 views
8

我有一个具有与Ninject连接的依赖关系的类。在类库中创建Ninject内核

public interface IFoo {} 

public class MyObject { 
    [Inject] 
    IFoo myfoo; 
} 

在真正的实现中,我使用属性注入,但只是为了快速说明,我将注入该字段。按照我的理解,而不是为MyObject的newing情况下,为了获得依赖于正确地注入,我需要使用

kernel.Get<MyObject>() 

但是我跌跌撞撞的事情是,为MyObject将只在使用类库的上下文。目的是让最终应用程序创建自己的模块并将其传递到内核实例中进行保湿。鉴于此,通常最实用的方法是将一个Ninject内核的通用实例展示给我的类库,以便MyObject(以及其他类似案例)的实例可以被水合?

我的第一个倾向是某种内部化单体内核的工厂 - 应用程序本身必须通过加载模块来进行水合/初始化。

所以在RandomService.cs

var myKernel = NinjaFactory.Unleash(); 
var myobj = myKernel.Get<MyObject>(); 
myobj.foo(); 

我走的太远了这条路,虽然之前,我需要做一个全面的检查,以确保思想是健全或不存在一些明显的其他我错过的东西。对于IoC来说,我显然是新手,并且觉得我非常喜欢基础知识,但不一定是现实世界中最好的方式。

回答

9

我不确定我是否理解了您的问题中的所有细节,但据我所知,您问的是如何将Ninject的依赖外化。

有可能写DI-friendly libraries without ever referencing any particular DI Container(Ninject或其他)。这使得图书馆的消费者可以选择他或她喜欢的DI容器(或根本不使用容器)。这种方法非常受欢迎,因为它提供了更大的自由度。

但是,您真的应该倾向于构造函数注入超过属性注入。虽然Property Injection看似简单易行,但实际上很难做到。

构造函数注入的一个重要优点是你不需要在构造函数中放置任何属性,因为它在结构上已经承载了DI容器正确连接所需的所有信息。

+0

幸运的是,这是一个内部(在公司的意义上)lib,所以我有一个被俘的观众 - 我的团队中的其他开发人员使用标准工具。现在,每个开发者可能有不同的绑定他们想要的,因此我原来的困惑。 回复:ctor vs道具注入,道具看起来似乎有很多我不得不写的东西,但是我担心随着时间的推移依赖列表不断增长,因此ctor调用。是否有其他缺点支持注射我应该注意? – bakasan 2010-02-11 08:50:19

+2

即使使用内部应用程序,我仍然会遵循相同的原则,因为它们会导致更清晰的代码,更好地分离问题。注入属性有许多潜在的问题,包括保护不变量(是依赖项null?),可能会热插拔注入的依赖项(可能不是您想要执行的操作)以及一般更模糊的API。 – 2010-02-11 09:08:41

+2

哦,只是为了预先考虑并明确表示:我认为服务定位器是一种反模式:http://blog.ploeh.dk/2010/02/03/ServiceLocatorIsAnAntiPattern.aspx – 2010-02-11 09:10:18

4

马克的观点绝对是我的出发点(因此+1)。 NB别忘了按照他的链接

我过去一直对构造函数在属性(或字段)上过早放弃(我的“借口”是因为基类需要5个属性,我不想用所有的派生类。解决这个问题的方法是包含5个属性,这些属性包含一个类或层次结构的类,它们表示属性所代表的任何基本概念。有点像引入参数对象重构。

我发现有用的考虑因素进行了很好的讨论是http://thinkbeforecoding.com/post/2009/05/15/IOC-container-go-hide(不能找到SO职位,提到它和周围的一些话题,也许有人会注入一个链接:d)

,总结了一些的另一个博客这些点是Your IoC Container is Showing

而且http://davybrion.com/blog/2009/11/integrating-your-ioc-container-with-agatha/

0

这里是寻找在当前汇编所有ninject模块一个很好的通用配方:

IKernel _serviceKernel = new StandardKernel(); 

Assembly myAssembly = this.GetType().Assembly; 

IEnumerable<Type> ninjectModuleTypes = 
    myAssembly.GetTypes().Where(type => type.BaseType == typeof(NinjectModule)); 

foreach (Type ninjectModuleType in ninjectModuleTypes) 
{ 
    NinjectModule mod = (NinjectModule)Activator.CreateInstance(ninjectModuleType); 
    _serviceKernel.Load(mod); 
}