9

既存の Windows フォーム アプリケーションに( Autofacを使用して) DI を導入しようとしています。

このアプリケーションには、各プラグインが独自のフォームを表示する基本的なプラグイン アーキテクチャがあります。起動時に、アプリケーションは を実装する型の登録済みアセンブリをスキャンしIPlugin、 を使用してこれらをアクティブ化しActivator.CreateInstanceます。

public interface IPlugin
{
    Form MainForm { get; }
}

このフレームワークを変更することはできません。つまり、各プラグイン クラスは DI 以外の方法でインスタンス化されるため、プラグインごとに個別の DI コンテナーをブートストラップする必要があるように思えます。

私の質問はContainerBuilder、プラグインごとに別のコンテナーを作成しても問題なく、それでもかなり効率的ですか? (約 10 の異なるプラグインがあります。) または、アプリケーション全体に対して 1 つの 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 { /* ... */ }

また、プラグイン コンストラクターでコンテナーを作成し、単にそれを忘れているかどうかもわかりませんが、バックグラウンドで自動配線を行うためにそのままにしておいても問題ありませんか?

4

2 に答える 2

7

コンテナーの使用は、 Register Resolve Release パターン(RRR)に従うのが理想的です。現在の Activator.CreateInstance の使用法を変更することはできないとおっしゃっていたことは承知していますが、それが実際にどうあるべきかを理解することは依然として役に立ちます。

その制約がない場合は、親アプリケーション自体によってホストされるコンテナー インスタンスが 1 つだけ存在する必要があります。これを使用して、すべてのプラグインを構成できます。これにより、プラグインが依存関係を共有できるようになります。これは MEF がたどるルートであり、拡張性のシナリオにも対応しています。

今、それができないので、あなたができる次善の策は、あなたが提案するようにプラグインごとにコンテナを持つことです. その時点で、ほとんどが実装の詳細になります。各プラグインでは、引き続き RRR パターンに従う必要があります。

非効率になりますか?多くのプラグインがあり、それらを常に作成および破棄しない限り、いくつかの異なるコンテナーはそれほど重要ではありません。ただし、時期尚早の最適化を作成するよりも、測定する方が適切です。

このシナリオでは、コンテナーを静的にすることによってのみコンテナーを共有できます。ただし、これは必要以上に複雑になるため、絶対に必要な場合を除き、その方法を使用しないでください。

于 2010-10-15T11:42:27.340 に答える
1

また、プラグイン コンストラクターでコンテナーを作成し、単にそれを忘れているかどうかもわかりませんが、バックグラウンドで自動配線を行うためにそのままにしておいても問題ありませんか?

何ヶ月も後に私自身の質問を見て、container(a) それはそうでIDisposableあり、そのように扱われるべきであり、(b) 一部のコンポーネントの寿命はコンテナにバインドされているため、コンテナのライフタイムは明示的に終了する必要があります。フォームのDisposeメソッド内であろうと、そのFormClosedイベントがトリガーされたときであろうと。

于 2012-02-05T20:15:25.737 に答える