插件体系结构中的DI(Autofac):每个插件一个单独的DI容器可以吗? [英] DI (Autofac) in a plugin architecture: Is one separate DI container per plug-in OK?

查看:243
本文介绍了插件体系结构中的DI(Autofac):每个插件一个单独的DI容器可以吗?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试将DI(带有 Autofac )引入现有的Windows Forms应用程序中。

I am trying to introduce DI (with Autofac) into an existing Windows Forms application.

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

This application has a basic plug-in architecture where each plugin displays its own form. On startup, the application scans registered assemblies for types that implement IPlugin, and then activates these using Activator.CreateInstance:

public interface IPlugin
{
    Form MainForm { get; }
}

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

I cannot change this given framework. This means, each plugin class is instantiated through non-DI means, and it seems to me that I will therefore have to bootstrap a separate DI container for each plugin.

我的问题是,是否正在为每个插件创建单独的 ContainerBuilder 和容器,还算合理? (大约有10个不同的插件。)或者整个应用程序应该只有一个DI容器吗?

My question is, is creating a separate ContainerBuilder and container per plugin OK and still reasonably efficient? (There will be approx. 10 different plugins.) Or should there only be one DI container for the whole application?

我已经提供了当前解决方案的一些示例代码

I've provided some sample code of my current solution below.

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 { /* ... */ }

我也不知道是否在插件构造函数中创建了一个容器,然后就忘记了,但是让它在后台自动布线可以吗?

I'm also not sure whether creating a container in the plugin constructor and then simply forgetting about it, but leaving it to do auto-wiring in the background, is OK?

推荐答案

您的容器用法理想上应遵循注册解析发布模式(RRR)。我知道您说过您不能更改当前Activator.CreateInstance的用法,但了解它的真实情况仍然很有帮助。

You container usage should ideally follow the Register Resolve Release pattern (RRR). I know that you said that you can't change the current Activator.CreateInstance usage, but it can still be helpful to understand how it really ought to be.

没有这种约束,只能有一个由父应用程序本身托管的容器实例。然后可以使用它来构成所有插件。这将使插件能够共享依赖关系。这是MEF采取的方法,它也解决了可扩展性方案。

If you didn't have that constraint, there should only be a single container instance, hosted by the parent application itself. This could then be used to compose all the plugins. This would enable the plugins to share dependencies. This is the route taken by MEF, which also addresses extensibility scenarios.

现在,由于您无法做到这一点,因此,下一个最好的选择就是拥有根据您的建议为每个插件提供一个容器。此时,它主要成为实现细节。在每个插件中,您仍然应该遵循RRR模式。

Now, since you can't do that, the next-best thing you can do is to have a container per plugin as you suggest. It mostly becomes an implementation detail at that point. In each plugin, you should still follow the RRR pattern.

效率低下吗?除非您有很多插件并始终创建和销毁它们,否则几个不同的容器应该没什么大不了的。但是,测量比创建过早的优化要好。

Would it be inefficient? Unless you have a lot of plugins and create and destroy them all the time, a couple of different containers shouldn't matter much. However, it's better to measure than to create premature optimizations.

在这种情况下,您只能通过使其静态共享一个容器。但是,这会使事情变得比原本要复杂的多,因此除非绝对必要,否则不要走那条路。

In this scenario, you can only share a container by making it static. However, this makes things more complicated than they need to be, so don't go that route unless absolutely necessary.

这篇关于插件体系结构中的DI(Autofac):每个插件一个单独的DI容器可以吗?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆