7

現在我有一些服務是在不依賴IoC容器的組件中定義的(Ninject就是我的情況)。在主項目中,我有一個在容器中註冊的用於數據訪問的IRepository。一般IoC實踐 - 服務互相依賴是錯誤的嗎?

this.Bind<IRepository>().To<EntityFrameworkRepository<MyDatabaseEntities>>(); 

我也有IAuthenticationService和IErrorLogger服務註冊,其具體實現我想爲他們的邏輯使用存儲庫。但是,我不知道如何最好地完成這一點。目前,我的兩個具體實現構造採取IRepository參數,我通過它時,我註冊他們:

this.Bind<IAuthenticationService>().To<MyAuthenticationService>(). 
       WithConstructorArgument("myRepository", ctx => ctx.Kernel.Get<IRepository()); 

在這裏,我只是告訴容器搶IRepository實例,並把它傳遞給構造函數。

我覺得我的服務程序集依賴於ninject甚至是公共服務定位器(CSL),但我不確定我目前的方式。我正在尋找意見和替代解決方案。

如果我的其他服務沒有使用IRepository,我將不得不爲每種底層IRepository類型(例如假冒和真實數據的AuthenticationService)創建這些服務的新具體實現。這將是很多邏輯重複。

回答

6

您的服務程序集不應該依賴於Ninject,只能在您註冊具體類型的接口上。 IoC容器應該只是將依賴關係注入到類中的聚合根。另一方面,包含聚合根/ Ninject內核的程序集將取決於包含具體類型的所有程序集(它們還能如何解決它們?)。

一般使用IoC,你應該申請在這裏Hollywood principle - 你應該依賴於你的具體對象實例(使用構造器注入,如果可能的話),而不是讓對象實例對它們的依賴。

不應該在所有的實際需要您使用WithConstructorArgument()的例子,因爲依賴解析工作遞歸:你已註冊的兩個IRepositoryIAuthenticationService與容器,所以它知道如何解決兩者。由於IAuthenticationService綁定到AuthenticationService,因此它不需要指定構造函數參數,因爲它的類型爲IRepository,並且將自動解析。

至於重複 - 當然你必須創建不同的實現IRepository針對不同類型的數據倉庫假設你想要這些庫的不同的行爲

+0

偉大的信息!你是對的,我根本不需要指定WithConstructorArgument。他們被自動注入。另一個問題是如果我註冊2個IRepository實現,每個實例都有不同的名稱。然後我想指定要注入的那個。我知道Ninject有一個NamedAttribute,但爲了避免在我的服務程序集中添加Ninject依賴項,我不想使用它。所以在這種情況下手動指定將是方法?僅供參考,我的重複擔心不是關於IRepository,而是其他服務類別。 – Adam 2012-02-13 19:11:09

+2

對於Ninject,你可以使用'WhenInjectedInto ()'其中Foo是你的服務類。通常情況下,您只會註冊您的存儲庫的一個具體實現 - 虛假數據和測試的註冊不應該作爲主應用程序的一部分註冊,只能在單獨的測試容器中註冊 – BrokenGlass 2012-02-13 19:17:33

+0

完美,再次感謝。 – Adam 2012-02-13 19:19:21