2010-09-28 80 views
6

我一直在閱讀關於控制反轉的框架,我只是在玩弄這個問題:「爲什麼在地獄中我需要一個框架來做到這一點?爲什麼要使用IoC框架

不要誤解我的問題......模式是我們程序員經常使用的東西,但是......一個全功能的框架來做到這一點?

我必須錯過一些東西,這就是我發佈這個問題的原因。我在網上看到了很多例子,我只是不明白。也許,我的思想被阻止了。

只要看看在Ninject主頁的例子:

public class Samurai { 
    public IWeapon Weapon { get; private set; } 
    public Samurai(IWeapon weapon) { 
     Weapon = weapon; 
    } 
} 

public class WarriorModule : NinjectModule { 
    public override void Load() { 
     Bind<IWeapon>.To<Sword>(); 
    } 
} 

的「武士」級是確定了我。 「NinjectModule」框架對我來說似乎沒有必要。

我後來假設我們將創建傳遞「亮劍」的實例給它新的「武士」的實例代碼,類似:

Samurai theWarrior = new Samurai(new Sword());//still no coupling 

Samurai theWarrior = new Samurai(WarriorModule.GetInstance(IWeapon));//no coupling 

可能被替換

Samurai theWarrior = new Samurai(GetWeaponFromXML());//no coupling yet 

什麼是部分我失蹤?你能否介紹一下我的應用程序需要Ioc框架的情況?

謝謝。

4個答案後的更新:我真的很喜歡我從你們那裏得到的所有答案。我剛剛閱讀了這篇文章dependency-injection-dissection/,其中這個人使用它來進行單元測試和剛纔提供的StackOverflow鏈接,是的,我錯過了大 - 大 - 複雜的部分,所以讓我自定義使用IoC框架。再次感謝。

我會投你的答案,但我只是得到一個橙色的消息,說我不能。

感謝那些突出顯示我發佈的代碼的人。

+1

我建議修改你的問題,使代碼塊實際的代碼塊,方法是'亮並按CTRL-K '或者在每行代碼的前面插入四個空格。 – jcolebrand 2010-09-28 18:50:35

+0

'新武士(新劍()); //仍然沒有耦合'這裏有一個緊密的耦合,你使用'new'。當你重構它時,你必須改變實例化劍的每個地方。 – nos 2010-09-28 18:54:03

+0

[爲什麼需要IoC容器而不是簡單的DI代碼?](http://stackoverflow.com/questions/871405/why-do-i-need-an-ioc-container-as-opposed -to-straightforward-di-code) – 2010-09-29 12:10:46

回答

4

你的例子是非常簡單的只具有兩層,但是當你有一個現實生活中的例子它很快就會變得混亂:

var form = new OrderEntryForm(
    new OrderService(
     new OrderReposity(
      new DatabaseGateway(
       new DataProviderFactory())))) 

IoC容器可以完成所有連線了你,讓你生活更容易。

這是一個類似的問題,它出現在所有細節的例子: https://stackoverflow.com/questions/45191/ioc-explain-and-more-important-when-to-use-it/45197#45197

+0

IoC容器如何降低複雜性?我的意思是你仍然會定義整個樹,但必須使用另一種更容易出錯的語言。 – 2013-11-29 11:01:27

6

這是代碼示例的問題。他們要麼複雜,你沒有解釋你的觀點,或者他們是微不足道的,然後顯得毫無意義。

WarriorModule正在做什麼是將具體類型綁定到接口,所以無論何時需要實現該接口的其他類都會由IoC容器自動接收一個類。具有依賴關係的類不依賴於具體類型,因此具有較低的耦合度和較高的可測試性。我想你已經知道了。

在您的替換方案中,Samurai類不與劍類耦合,但調用代碼仍然存在。你可以把它推出另一個級別,但是這段代碼現在有了依賴關係,你的干涉類現在必須編組所有的依賴關係。

IoC容器爲所有映射執行此操作,只將它放在幾個位置(模塊類)中。其餘的代碼是免費的,不要在意,不要依賴具體的類型。

希望有所幫助。

+0

喜歡此評論; 「這是代碼示例的問題,它們要麼很複雜,你沒有解釋你的觀點,或者它們微不足道,然後顯得毫無意義。」我通常會對後者說更多的話。特別是對於Ninject,沒有任何實例證明它的使用是合理的,因爲它們太簡單了,並且沒有展示任何使得它在手工DI之外更有價值的細節。 – 2011-04-21 16:27:29

+0

如果你有一個好的設計,你根本沒有太多的耦合。如果我在一個地方用XML或代碼定義接線,那麼差異在哪裏? – 2013-11-29 11:03:29

1

我最近開始使用Unity for IoC,毫無疑問,它讓我的生活更輕鬆。

我只會逐字粘貼我的代碼,並希望您覺得它很有用。更有經驗的人可能會給你更多。

另外,我發現閱讀Fowler關於DI的論文很有用。

static class Program 
{ 
    [STAThread] 
    static void Main() 
    { 
     Application.EnableVisualStyles(); 
     Application.SetCompatibleTextRenderingDefault(false); 

     using (IUnityContainer container = new UnityContainer()) 
     { 
      container 

       .RegisterType<ILogger, StatSyncherFormView>(new myLife()) 

       // GUI 
       .RegisterType<IStatSyncherView, StatSyncherFormView>() 

       // Services 
       .RegisterType<ISalesForceWebServices, SalesForceWebServices1>() 

       .RegisterInstance(new SalesForceWebServices1(
        "XXX", "XXX", 
        "https://login.salesforce.com/services/Soap/c/19.0/0DF70000000CfHq", 
        "https://na5-api.salesforce.com/services/Soap/s/19.0")) 


       .RegisterType<ISalesForceService, SalesForceService1>() 

       .RegisterType<IRestApiCall, RestApiCall1>() 

       .RegisterType<IDirectTrackService, DirectTrackService1>() 

       .RegisterType<IDAgentsService, DAgentsService1>() 

       .RegisterType<IQuickBooksService, QuickBooksService1>(); 

      StatSyncherPresenter p = container.Resolve<StatSyncherPresenter>(); 

      Application.Run((Form)p.view); 
     } 
    } 

一個我認爲最有用的東西是:

public class AnyClassCreatedByContainer 
{ 
    [Dependency] 
    public ILogger Logger { get; set; } 
} 
1

雖然Samurai theWarrior = new Samurai(new Sword());仍然沒有連接,如果你想給所有的武士在應用程序中<insert favourite weapon here>,你就必須改變你所有的通話密碼都會變成新的武器,而使用IoC你可以在一個地方改變它,所有的武士都會使用新的武器。

相關問題