2011-06-09 29 views
0

我一直依靠IoC模式1年,現在使用結構圖& asp.net mvc。 IoC真的很整潔,特別是如果你的類中有很多依賴項,只需在構造函數中注入依賴項並完成,IoC就會爲你自動注入它。關於IoC的問題

我的問題是即時通訊使用asp.net mvc與具有IServices依賴關係的控制器類。

我只需要某個控制器動作的依賴項服務讓我們說「/ customer/add」 但我不需要那些依賴於其他動作比如說「/ Customer/Index」。但是,由於我在構造函數中使用了DI(依賴注入),所以即使我不需要它們,依賴也總是被實例化。這有什麼好處?對象創建非常昂貴並佔用內存佔用量。

當然,我可以在一個動作中執行container.GetInstance,但這不是一個好的做法,因爲在代碼和單元測試中您將嚴重依賴於IoC。

有什麼建議嗎?糾正我,如果我錯了什麼。

+1

如果這是您系統中的瓶頸,那麼您會遇到更大的問題。我不會爲此擔心。 – 2011-06-09 19:27:12

+1

這種擔憂似乎是在性能分析之前進行優化的一個例子 - 當然這是倒退的。 – 2011-06-09 19:40:27

回答

4

更新響應jgauffins評論

我看到了兩個簡單的方法來解決您的問題:

注入一個服務工廠的建設者和創造需求的服務。

interface IFooService 
{ 
    void Bar(); 
} 

interface IFooServiceFactory 
{ 
    IFooService CreateFooService(); 
} 

class YourController 
{ 
    public YourController(IFooServiceFactory fooServiceFactory) 
    { 
     this.fooServiceFactory = fooServiceFactory; 
    } 

    public void YourAction() 
    { 
     IFooService fooService = this.fooServiceFactory.CreateFooService(); 
     fooService.Bar(); 
    } 
} 

注入一個服務代理,以你的構造,讓代理按需創建真正的服務。

interface IFooService 
{ 
    void Bar(); 
} 

class FooServiceProxy : IFooService 
{ 
    private IFooService realFooService; 


    void IFooService.Bar() 
    { 
     IFooService realFooService = GetRealFooService(); 
     realFooService.Bar(); 
    } 

    private IFooService GetRealFooService() 
    { 
     if(this.realFooService == null) 
     { 
      this.realFooService = CreateRealFooService(); 
     } 
     return this.realFooService; 
    } 

    private IFooService CreateRealFooService() 
    { 
     // You could inject the service factory in the constructor of the proxy and use it here to create the real service. 
    } 
} 

class YourController 
{ 

          Inject FooServiceProxy here 
          v 
          v 
    public YourController(IFooService fooService) 
    { 
     this.fooService = fooService; 
    } 

    public void YourAction() 
    { 
     this.fooService.Bar(); 
    } 
} 
+0

工廠和延遲加載代理的+1。但是,代理應該在實例解決時保持實例,而不是在每種方法中查找。將它包裝在一個屬性中,該屬性檢查成員變量是否爲空(然後將其實例化) – jgauffin 2011-06-09 19:54:41

+0

謝謝,我更新了我的答案 – 2011-06-09 20:01:41

+0

cool dude。這是我需要的設計模式,但這可能會帶來我的代碼中的複雜性,我想知道,因爲。在不同的控制器中,我將有不同的依賴關係,因此不同的工廠..但答案被接受。 – 2011-06-10 08:45:29

1

我一直在做的方式是,對於注入的依賴是可選(如在情況下,你剛纔所描述的只有某些方法需要依賴),將它們設置爲性能。對於需要依賴項,請使用構造函數注入。

+2

在我看來,服務依賴關係_is_是必需的,因爲整個類都需要它,並且不會在服務不存在的情況下工作。 – 2011-06-09 19:40:53

4

我總是使用構造函數。恕我直言屬性應該只用於解決循環依賴。

原因是,使用屬性時意圖不明確。如果未設置屬性MyController.MyProperty,代碼中的任何內容都不會顯示MyController.DoThat將不起作用。

如果一個方法需要一個特定的服務,那麼這個服務是你整個班級所需要的。否則你會打破你的班級公開的合同。

+0

+1,用於指出財產注入的弱點。 – 2011-06-09 19:41:40

+0

服務依賴可以使用懶惰的實現注入,不可以? – BlackTigerX 2011-06-09 21:24:59

+0

@BlackTigerX:但即使依賴是懶惰的,你仍然會注入一個依賴項,而不是null(除了單元測試以外)。 – Steven 2011-06-10 08:30:15

3

的依賴始終即使實例化,如果我不需要它們。這有什麼好處?

雖然不是每一個類的一部分需要依賴,類本身需要一個依賴,因此這是一個可選的依賴。通常,當你看到某些依賴關係在類的一部分中使用,而在另一部分中使用其他依賴關係時,你的類可能違反了SRP;它可能會做更多的事情。然而,將它們分開,可能不會對您有所幫助,因爲MVC Controller類更專注於接口,所以我只是將它保留原樣。

對象創建是昂貴的並消耗內存佔用。

引用類型總是有8個字節的開銷(在32位平臺上),所以這不是太大。您通常注入的服務對象包含的狀態很少,通常只是一些配置值和對其依賴關係的引用。從內存角度來看,與通過應用程序流動的數據(例如數據庫中的數據或MVC生成的用於生成HTML的字符串)相比,沒有任何差別。它的確取決於你使用的DI框架,但通常情況下,即使是相對較大的依賴關係圖也會在短時間內生成。即使圖形構建花費太多時間,還有其他方法可以優化性能。考慮以單身生活方式來定義一些服務。當這還不夠時,您可能需要考慮切換到更快的DI框架。然而,結構圖是該領域的fasterDI容器之一(更常見的),所以對於正常的應用開發來說,這應該不成問題。

+0

謝謝史蒂文。這也是我的猜測,你更清楚並確認它。這也是一個很好的答案,因爲我不想在代碼中增加複雜性。我只是投你的答案。 – 2011-06-10 08:47:55

0

StructureMap支持延遲實例化 - 無需構建自己的服務工廠/代理解決方案。如果您只想在使用動作時實例化IService,請將Func<IService>注入到您的構造函數中。然後,在你需要的動作中,調用Func返回實例。

class CustomerController { 
    Func<IService> _service; 

    public CustomerController(Func<IService> service){ 
    _service = service; 
    } 

    public ActionResult Index(){ 
    _service().CallMethodOnService(); 
    } 
} 

但是,我會首先確保在進行這項額外工作之前實例化服務真的是性能問題。