2009-09-22 56 views
2

我試圖讓我的業務邏輯組件查詢服務時,他們被添加到我的窗體/控件類之一。例如,我的庫中可能有一個ClientManager類,它封裝了一些業務邏輯。它需要一個ILoginManager實例來查詢它需要操作的一些數據。如何在WinForms應用程序中使用System.ComponentModel中的服務定位器實現進行依賴項注入?

具體ILoginManager實例是在WinForms應用程序中創建的,例如作爲一個單例。我希望能夠將一個ClientManager組件放置到表單上,這將使ILoginManager實例可以自動用於組件。

從我從this article on lightweight containers明白,我可以用GetService的實現這一點:

public class ClientManager : Component 
{ 
    public ClientManager() {} 
    public ClientManager(IContainer container) { 
     container.Add(this); 
    } 

    public ILoginManager User 
    { 
     // would really be cached in a private field 
     get { return GetService(typeof(ILoginManager)) as ILoginManager; } 
    } 

    // does something that requires the User property to be set 
    public void DoSomething(); 
} 

我將不得不重寫的GetService返回我的實例的容器:

public class MyContainer : Container 
{ 
    ServiceContainer svc; 

    public MyContainer() { 
     svc = new ServiceContainer(); 
     svc.AddService(typeof(ILoginManager), GlobalAppStuff.LoginManager); 
    } 

    protected override object GetService(Type service) { 
     return svc.GetService(service); 
    } 
} 

作爲一個獨立的解決方案,這工作得很好,但我無法弄清楚如何將其集成到一個可設計的控件中,因爲設計器始終生成一個默認的容器,並且我不知道有任何向其中注入服務的方法。

MSDN文檔在描述應該如何實際使用這些概念時含糊不清。有什麼簡單的方法可以使用設計器友好的ComponentModel類來完成此操作嗎?

回答

2

不要使用System.IServiceProvider進行DI--它主要用於設計時使用。對於IComponent實現,VS設計人員將爲Site屬性賦值,這就是整個IServiceProvider機制的功能,但是該屬性在運行時將爲空,這意味着您對GetService的所有調用都將失敗。

你會過得更好使用適當的DI容器,如溫莎城堡,StructureMap等

+1

城堡不允許我到我的組件拖動到一個形式,因爲它使用了構造函數注入。 StructureMap使用了一個我不喜歡的靜態對象,因爲它將我的對象專門綁定到StructureMap。看起來基本的.NET組件已經支持我需要的大部分內容,這只是讓它與設計師合作的麻煩。 – 2009-09-22 11:46:55

+0

也許,但即使這很困難,它也只會*在設計師身上工作。運行時IComponent.Site將爲空,但它是提供IServiceProvider實現的ISite值,所以它不會在運行時工作。 – 2009-09-22 12:46:06

+0

我不確定這就是它的全部。設計師沒有設置ISite - 容器。設計人員在設計時使用自己的System.ComponentModel.Design.DesignerHost容器。一個應該能夠在運行時提供自己的容器,並且Visual Studio實際上爲其生成代碼,但是我不知道如何覆蓋它生成的容器類型。 – 2009-09-22 13:35:51

相關問題