插件架构中的DI(Autofac):每个插件有一个单独的DI容器吗?

我试图将DI(使用Autofac )引入现有的Windows窗体应用程序。

此应用程序具有基本的插件体系结构,其中每个插件都显示其自己的表单。 在启动时,应用程序扫描已注册的程序集以查找实现IPlugin类型,然后使用Activator.CreateInstance激活它们:

 public interface IPlugin { Form MainForm { get; } } 

不能改变这个给定的框架。 这意味着,每个插件类都是通过非DI方式实例化的,在我看来,因此我必须为每个插件引导一个单独的DI容器。

我的问题是 ,每个插件创建一个单独的ContainerBuilder和容器OK还是合理有效吗? (将有大约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(); // ^ 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().SingleInstance(); // ... more plugin-specific registrations go here... } } internal class MainForm : Form { /* ... */ } 

我也不确定是否在插件构造函数中创建了一个容器然后只是忘了它,但是让它在后台进行自动连接,是否可以?

理想情况下,容器使用应遵循Register Resolve Release模式 (RRR)。 我知道你说你不能改变当前的Activator.CreateInstance用法,但它仍然有助于理解它应该如何。

如果您没有该约束,则应该只有一个容器实例,由父应用程序本身托管。 然后可以使用它来组成所有插件。 这将使插件能够共享依赖项。 这是MEF采用的路由,它也解决了可扩展性方案。

现在,既然你不能这样做,你可以做的下一个最好的事情是按照你的建议为每个插件设一个容器。 它主要成为那时的实现细节。 在每个插件中,您仍应遵循RRR模式。

会效率低吗? 除非你有很多插件并且一直在创建和销毁它们,否则几个不同的容器应该不重要。 但是,测量比创建过早优化更好。

在这种情况下,您只能通过使容器静态来共享容器。 然而,这使事情变得比他们需要的更复杂,所以除非绝对必要,否则不要走那条路。

我也不确定是否在插件构造函数中创建了一个容器然后只是忘了它,但是让它在后台进行自动连接,是否可以?

几个月后看着我自己的问题,我敢说忘记container是不行的,因为(a)它是IDisposable并且应该被视为这样,并且(b)某些组件的生命周期与容器绑定,因此容器的生命周期应该明确结束; 无论是在表单的Dispose方法中,还是在触发FormClosed事件时。