2009-04-20 81 views
41

有沒有人有IoC容器的良好示例(最好在C#中)以及如何以及爲何使用它們?我已經檢查了wiki pageAyende's的例子,但我還沒有完全理解這個概念。IoC容器的示例

何時何地應使用IoC容器?

回答

47

我已經使用structure map相當多。你的問題的其餘部分是相當的加載。我會試着在一個例子中解釋這個概念。

假設您創建了一個通過PayPal接受付款的網站。 PayPal現在是一個依賴項。但您不想針對特定PayPal提供商進行編碼。

相反,你會反對這樣的界面創建和代碼..

interface IPaymentProcessor 
{ 
     bool ProcessPayment(amount, ....); 
} 

所有你的PayPal代碼將駐留在實現你的接口方法的類。例如PayPalPaymentProcessor

現在您擁有了一個實際用於處理付款的對象。這可能是一個控制器(asp.net-mvc,ViewModel-wpf)或只是一個類,如圖所示。

class PaymentProcessor 
{ 
    private IPaymentProcessor _processor = null; 
    public PaymentProcessor(IPaymentProcessor processor) 
    { 
     _processor = processor; 
    } 

    public bool ProcessTransaction(Transaction trans) 
    { 
     _processor.ProcessPayment(trans.amount, ...); 
    } 
} 

這是一個IoC進來,而是你手動調用構造函數,你讓一個IoC 注入的依賴。

PaymentProcessor processor = ObjectFactory.GetInstance<PaymentProcessor>(); 

這段代碼告訴結構圖「你看,需要一個 IPaymentProcessor構造任何時候,返回一個新的PayPalPaymentProcessor」。

ObjectFactory.Initialize(x => 
{ 
x.ForRequestedType<IPaymentProcessor>().TheDefaultIsConcreteType<PayPalPaymentProcessor>(); 
}); 

所有這些映射是從您的實現代碼獨立的,你可以在所需要的小重構稍後換出這些。 IoCs還有很多,但這是一個基本概念。您可以自動注入構造函數以避免直接調用ObjectFactory。

希望這會有所幫助!

+0

感謝你的好例子:)。我明白問題的最後部分有點寬泛,但我認爲你也回答了這個問題。 – Morph 2009-04-20 21:22:37

+0

我可以提出一個更正嗎? PaymentProcessor獲取實例的代碼不應該是這樣嗎? `PaymentProcessor processor = ObjectFactory.GetInstance ();` – 2016-02-29 08:56:01

2

檢出Spring IoC (.net)一個java/.net容器。這個文檔是相當不錯的介紹。

在簡短: 你可以想想國際奧委會鼓勵的架構: 對象組成面向接口編程

這給你以下幾點:

  • 方便地測試你的代碼(你可以很容易地嘲弄了它所有的依賴隔離測試你的對象)的能力單元。

  • 非常先進的配置(因爲您的IoC程序只是一堆對象和將對象粘在一起的配置)。

  • 能夠擴展或修改字節編譯的應用程序(這對於Java來說是真實的我不確定它是否適用於.net)。

+0

謝謝,看起來像一個很好的閱讀! – Morph 2009-04-20 21:15:42

0

您是否試圖構建一個IoC容器,爲什麼不使用像Spring.NET,StructureMap或Unity Application Block這樣的可用容器? Here是一個開源IoC項目列表

+1

不,我並不是試圖建立一個,但這是我想要更好地理解的概念。 – Morph 2009-04-20 21:06:31

1

我通常使用StructureMap - 主要是因爲我熟悉語法。我也聽說過autofac的好消息,我期待在登錄v2時試用Ninject

您可能想看看this answer,我在這裏談論IoC容器的基本用法(我總是認爲事情比較容易理解,只是一個簡單的例子) - 這可能會幫助您更多地理解事情。基本上,IoC容器可以幫助您構建滿足所有依賴關係的對象,並允許您使用最少的配置代碼更改依賴關係。

2

我們使用Ninject是因爲它具有簡單的API和快速解析對象。它有很好的文檔記錄,並利用了諸如lambda表達式之類的C#3.0特性來使規範更容易。

您可以在Ninject here

0

我對我的IoC容器使用Unity,但容器之間的區別在於您可以使用DI執行的操作。

DI(依賴注入)主要是一種讓程序的不同部分之間更鬆散耦合的方式。所以,如果你寫了一個你喜歡它的遊戲,那麼通過使用DI你可以改變遊戲中的角色或物理引擎而不改變遊戲的其他部分,所以如果有人支付更多的錢,他們會得到更逼真的引擎,或更好的角色,但由於沒有其他更改,測試更簡單。

使用DI進行單元測試也比較容易,因爲您可以嘲笑數據庫,例如,只需更改應用程序將使用的實現,而不會影響其他任何內容。

如果你使用Spring.NET例如,你將可以訪問一個非常強大的框架,但它可能會做很多事情,你不會使用,所以尋找更小的東西。我認爲最好的規則是找到滿足您需求的最小,最簡單的實現,並使用它。

8

如果你想看到一個IoC容器和點(依賴注入),DNR電視上有一個很棒的播客(Episode 126),它詳細介紹瞭如何創建它們,爲什麼你會需要他們。這是一個非常棒的播客。觀看此視頻後,您將可以看到Unity,Ninject,StructureMap等,並能夠理解他們在做什麼

19

請注意IOC容器的以下限制。我必須警告人們,因爲我忍不住要支持使用它的系統:

  • 構造函數拋出的異常被吞下。你只會得到「無法創建依賴」的例外。這意味着如果拋出構造函數,就不能捕獲預期的異常。
  • 無法逐句通過構造函數。
  • 忘記註冊接口在運行時中斷而不是編譯時。
  • 所有的類只能有一個構造函數,它們都必須接受接口作爲參數。
  • 所有的依賴關係都被實例化,所以你不能共享實例,這意味着你的內存使用量可能很快變大。
  • 它促進了很多相互依賴,可以隱藏你編碼變成意大利麪的事實。讓所有這些相互依存更容易安置,只是掩蓋了潛在的潛在問題。
  • 您無法輕鬆管理自己的「工作單元」,因爲您無法管理跨多個依賴項的事務,因爲您無法控制實例化它們並傳遞該事務的上下文。

不要誤會我的意思,我喜歡依賴注入和控制原理的反轉,但我認爲IOC容器可以負責任地使用,但要知道,你將需要因爲打的戰役上面的列表。