2008-11-10 11 views
10

通常,我喜歡讓應用程序完全不瞭解IoC容器。但是,我遇到了需要訪問它的問題。爲了抽象出我使用基本單例的痛苦。在爲山丘奔跑或拔出霰彈槍之前,讓我先看看我的解決方案。基本上,IoC單例完全沒有任何問題,它只是委託給一個必須傳入的內部接口。我發現這使得單例工作變得不那麼痛苦。在Singleton後面抽象IoC容器 - 做錯了嗎?

下面是IoC的包裝:

public static class IoC 
    { 
     private static IDependencyResolver inner; 

     public static void InitWith(IDependencyResolver container) 
     { 
      inner = container; 
     } 

     /// <exception cref="InvalidOperationException">Container has not been initialized. Please supply an instance if IWindsorContainer.</exception> 
     public static T Resolve<T>() 
     { 
      if (inner == null) 
       throw new InvalidOperationException("Container has not been initialized. Please supply an instance if IWindsorContainer."); 

      return inner.Resolve<T>(); 
     } 

     public static T[] ResolveAll<T>() 
     { 
      return inner.ResolveAll<T>(); 
     } 
    } 

的IDependencyResolver:

public interface IDependencyResolver 
    { 
     T Resolve<T>(); 
     T[] ResolveAll<T>(); 
    } 

我已經到目前爲止與我用它幾次(每隔幾個項目,也許一次巨大的成功,我真的不喜歡使用這個),因爲我可以注入任何我想要的東西:城堡,存根,假貨等。

這是一條溼滑的道路嗎?我是否會遇到潛在的問題?

回答

4

我已經看到,即使Ayende在Rhino Commons代碼中實現了這種模式,但我建議不要在任何可能的地方使用它。 Castle Windsor默認沒有這個代碼是有原因的。 StructureMap的確如此,但Jeremy Miller一直在擺脫它。理想情況下,您應該將容器本身視爲與任何全局變量一樣多的懷疑。

但是,作爲替代方案,您始終可以配置您的容器以解析IDependencyResolver作爲對容器的引用。這聽起來很瘋狂,但它更加靈活。只要記住一個對象應該稱之爲「新」或執行處理的經驗法則,但不能同時處理兩者。對於「call new」,請替換爲「解析參考」。

3

這不是一個單獨的課程。這是一個靜態成員的靜態類。是的,這似乎是一個好方法。

我認爲JP Boodhoo甚至有這種模式的名稱。 The Static Gateway pattern

2

請注意:Microsoft模式和實踐已經創建了一個通用服務定位器(http://www.codeplex.com/CommonServiceLocator),大多數主要IoC容器將在不久的將來實現。您可以開始使用它而不是您的IDependencyResolver。

順便說一句:這是解決你的問題的常用方法,它工作得很好。

1

這一切都取決於用法。使用這樣的容器稱爲服務定位器模式。有些情況下它不適合以及適用的情況。

如果你谷歌「服務定位器模式」,你會看到很多博客文章說這是一個反模式,事實並非如此。該模式只是被濫用(/濫用)。

對於典型的業務線應用程序,在隱藏依賴關係時不應使用SL。您還遇到了另一個問題:如果使用根容器(而不是其生命週期中的一個),則無法管理狀態/生命週期。

當涉及到基礎設施時,服務定位器非常適合。例如,ASP.NET MVC使用Service Locator來解決每個控制器的所有依賴關係。