sta*_*ica 8 c# add-in dependency-injection autofac
我试图将DI(使用Autofac)引入现有的Windows窗体应用程序.
此应用程序具有基本的插件体系结构,其中每个插件都显示其自己的表单.启动时,应用程序扫描已注册的程序集以查找实现的类型,IPlugin然后使用Activator.CreateInstance以下命令激活它们:
public interface IPlugin
{
Form MainForm { get; }
}
Run Code Online (Sandbox Code Playgroud)
我无法改变这个给定的框架.这意味着,每个插件类都通过非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<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 { /* ... */ }
Run Code Online (Sandbox Code Playgroud)
我也不确定是否在插件构造函数中创建了一个容器,然后只是忘了它,但是让它在后台进行自动连接,是否可以?
理想情况下,容器使用应遵循Register Resolve Release模式(RRR).我知道你说你不能改变当前的Activator.CreateInstance用法,但它仍然有助于理解它应该是什么样的.
如果您没有该约束,则应该只有一个容器实例,由父应用程序本身托管.然后可以使用它来组成所有插件.这将使插件能够共享依赖关系.这是MEF采用的路由,它也解决了可扩展性方案.
现在,既然你不能这样做,你可以做的下一个最好的事情是按照你的建议为每个插件设一个容器.在这一点上,它主要成为一个实现细节.在每个插件中,您仍应遵循RRR模式.
会效率低下吗?除非你有很多插件并且一直在创建和销毁它们,否则几个不同的容器应该不重要.但是,测量比创建过早优化更好.
在这种情况下,您只能通过使容器静态来共享容器.然而,这使事情变得比他们需要的更复杂,所以除非绝对必要,否则不要去那条路线.