2010-02-11 33 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); 
}