2013-07-02 22 views
4

我有我的Windows窗體應用程序的工作初始的Unity DI容器。在Program.cs我有以下幾點:如何在下游產生新的Windows窗體時使用DI?

static void Main() 
{ 
    var container = BuildUnityContainer(); 
    Application.EnableVisualStyles(); 
    Application.SetCompatibleTextRenderingDefault(false); 
    Application.Run(container.Resolve<MainForm>()); 
} 

private static IUnityContainer BuildUnityContainer() 
{ 
    var container = new UnityContainer(); 
    container.RegisterType<ITest, MyTestClass>(); 
    container.RegisterType<ISomeOtherTest, MyOtherClass>(); 
    return container; 
} 

在我MainForm構造我有以下它確實工作

private readonly ITest test; 

     public MainForm(ITest test) 
     { 
      this.test = test; 
      InitializeComponent(); 
     } 

容器被解決,代碼工作正常。問題/問題是,我該如何實例化一個新的形式從MainForm,說Form2具有以下構造:

private readonly ISomeOtherTest someOtherTest; 

    public Form2(ISomeOtherTest someOtherTest) 
    { 
     this.someOtherTest = someOtherTest; 
     InitializeComponent(); 
    } 

如果我嘗試在我MainForm如下:

Form2 form2 = new Form2(); 
form2.Show(); 

這將打破,抱怨說我沒有把值提供給構造函數。不過,我已經解決了我的容器,我認爲所有的下游容器都將得到解決。顯然我在這裏錯過了一些東西,因爲它不起作用。

這是否意味着我必須前負荷所有依賴到MainForm即使形式不使用它,所以我就可以將它們傳遞到任何新形式的實例我做什麼呢?如果我有50個依賴關係需要解析並且頂層表單的構造函數將它們全部取出,那將會很奇怪。請幫助理清我的理解,因爲我幾乎專門在Web API和MVC中使用了Unity和DI容器,並且已經爲控制器內置了DI解析器,所以我必須在這裏丟失一些片斷和理解。

+0

DI效果很好與ASP.NET,因爲對象創建是通過管道委託,他們把自己放在那裏。在WinForm/WPF中,大部分時間需要通過容器創建該類型。此外,如果你需要更多的幫助,你至少應該告訴你正在使用哪個DI(Unity,Ninject等)。 –

+2

@SimonBelanger - 請在我的帖子中閱讀第4個單詞:「我有* Unity * DI .. 。「我的最後一段說到:」我用過* Unity * ...「你讀得太快了,請提供一些例子而不是抽象描述。 – atconway

+0

@atconway,出色的問題。我自己也在努力解決這個完全相同的問題。 – MEMark

回答

6

您應該創建表單像這樣

Form2 form = container.Resolve<Form2>(); 

你沒有使用容器,因此表沒有一個構造函數,不帶任何參數。如果你用容器解決它,它將檢查構造函數,找到依賴關係並自動將它們注入到構造函數中。

所以..也許你的問題是,你沒有訪問您的MainForm中的容器?如果是這樣的問題,有兩種方法..

進樣IUnityContainer到MainForm的構造

但是......誰住的「組成根」模式的人會告訴你,你應該只使用容器從你的應用程序的根目錄(在這種情況下,可能Main())另一個選項是...

從您的組合根(主),它被注入到MainForm和MainForm使用工廠創建一個Form2工廠類創建Form2

你應該更多地閱讀構思根的思想理論......

Composition Root


更新

我以前從來沒有做到這一點,但我認爲第二種方法會是這個樣子......

public class Form2Factory : IForm2Factory 
{ 
    private readonly ISomeOtherTest someOtherTest; 

    public Form2Factory(ISomeOtherTest someOtherTest) 
    { 
     this.someOtherTest = someOtherTest; 
    } 

    public Form2 Create() 
    { 
     return new Form2(someOtherTest); 
    } 
} 


public class MainForm 
{ 
    private readonly IForm2Factory form2Factory; 

    public MainForm(IForm2Factory form2Factory) 
    { 
     this.form2Factory = form2Factory; 
    } 

    private void DoingSomething() 
    { 
     Form2 form = form2Factory.Create(); 
     form.Show(); 
    } 
} 
+0

如何在我的'MainForm'中訪問'容器'變量?這是在'Program.cs'中只聲明的,我在Intellisense中看不到它。我應該以某種方式通過它嗎? – atconway

+0

@atconway:聲明'container'爲public。 – Steven

+0

我將不得不聲明它爲'public static IUnityContainer container = new UnityContainer();'因爲'Program.cs'是一個'static'類。這是做這件事的正確方法嗎? – atconway

相關問題