2010-10-15 26 views
7

我正試圖在現有的Windows Forms應用程序中引入DI(與Autofac)。插件體系結構中的DI(Autofac):每個插件都有一個單獨的DI容器可以嗎?

此應用程序有一個基本的插件體系結構,其中每個插件顯示自己的窗體。在啓動時,應用程序掃描組件註冊爲實現IPlugin類型,然後激活這些使用Activator.CreateInstance

public interface IPlugin 
{ 
    Form MainForm { get; } 
} 

不能改變這個既定框架。這意味着,每個插件類都是通過非DI方式實例化的,在我看來,因此我必須爲每個插件引導一個單獨的DI容器。

我的問題是,是創建一個單獨的ContainerBuilder和容器每插件確定,仍然合理高效? (將會有大約10個不同的插件。)或者應該只有一個DI容器用於整個應用程序?

我在下面提供了一些我當前解決方案的示例代碼。


using Autofac; 
using System.Windows.Forms; 

public class Plugin : IPlugin // instantiated by Activator 
{ 
    public Form MainForm { get; private set; } 

    public Plugin() // parameter-less constructor required by plugin framework 
    { 
     var builder = new ContainerBuilder(); 
     builder.RegisterModule(new Configuration()); 
     var container = builder.Build(); 

     MainForm = container.Resolve<MainForm>(); 
     //^preferred to new MainForm(...) because this way, I can take 
     // advantage of having dependencies auto-wired by the container. 
    } 
} 

internal class Configuration : Module 
{ 
    protected override void Load(ContainerBuilder builder) 
    { 
     builder.RegisterType<MainForm>().SingleInstance(); 
     // ... more plugin-specific registrations go here... 
    } 
} 

internal class MainForm : Form { /* ... */ } 

我也不能肯定是否在插件的構造函數創建一個容器,然後簡單地忘記這件事,但離開它做自動裝配的背景下,是OK?

回答

7

您的容器使用情況理想情況下應遵循Register Resolve Release pattern(RRR)。我知道你說你不能改變當前的Activator.CreateInstance用法,但它仍然可以幫助理解它應該如何。

如果您沒有該約束,應該只有一個容器實例,由父應用程序本身託管。這可以用來組成所有的插件。這將使插件可以共享依賴關係。這是MEF採用的路由,它也處理可擴展性場景。

現在,由於您無法做到這一點,您可以做的下一個最好的事情就是按照您的建議爲每個插件安裝一個容器。它在這一點上大多成爲一個實現細節。在每個插件中,您仍應遵循RRR模式。

效率低下嗎?除非你有很多插件並且一直創建並銷燬它們,否則幾個不同的容器應該不會太重要。但是,測量比創建不成熟的優化要好。

在這種情況下,您只能通過使其靜態共享容器。但是,這會讓事情比他們需要的更復雜,所以除非絕對必要,否則不要走這條路。

+0

感謝您回覆@Mark。如果我理解正確,我的示例代碼已經遵循RRR模式......對吧? (除了我不釋放容器,因爲它需要至少和根組件'MainForm'一樣長,我想,理想的方法是讓插件'IDisposable'並釋放'Dispose'方法中的容器。) – stakx 2010-10-15 11:52:15

+2

代碼中沒有任何內容表明您沒有遵循RRR,但很難說。無論如何,請記住SingleInstance生活方式只定義一個容器範圍的Singleton。這不是一個真正的Singleton,所以你不能以這種方式共享MainForm。 – 2010-10-15 11:59:23

0

我也不能肯定是否在插件的構造函數創建一個容器,然後簡單地忘記這件事,但離開它做自動裝配的背景下,是OK?在我自己的問題

尋找許多個月後,我敢說,只是忘記container也不行,因爲(一)它是IDisposable,應受到同樣的對待,和(b)某些組件的壽命都綁定在容器上,因此容器的壽命應該明確地結束;可以使用表單的Dispose方法或觸發其事件FormClosed