5

.NET 3.5 アプリケーション (WinForms) 用の単純なプラグイン フレームワークを設計しています。

現在のアプリケーションは、コンパイル時にアプリケーションに認識されていないさまざまな「プラグイン」/「拡張機能」の動的ロードと「フック」のサポートを開始する必要があります。

これらの拡張機能は、特定のクラスのイベント ハンドラーとして追加されるなど、アプリケーションのさまざまな領域に "フック" されます。

例(簡略化):

public class SomeSystem
{
     public event Action<string> Completed;

     public event Action<string> Failed;

     public event Action<string> Stopped;
}

私が望んでいる使用例の 1 つは、開発者がプラグイン アセンブリでそのようなイベントのハンドラーをアプリケーションに認識させることなく定義できるようにすることです。

私の知る限り、IoC コンテナーを使用すると、実行時にオブジェクトを動的に検出し、それらをコンテナーに登録できます。

IoC コンテナーは、さまざまなイベントにフックすることもできますか? それとも、そのようなフレームワークなしでこのタスクを実行する方が簡単ですか?

このようなタスクのために IoC コンテナーを統合する方法を設計するにはどうすればよいでしょうか? (登録に使用できるさまざまなイベントなど、複数の拡張ポイントがあるとします)。

私が自分自身に尋ねていることがわかったいくつかの質問:

  1. プラグイン自体が登録を行うためのRegisterメソッドを提供するのは一般的ですか?
  2. IoC が登録を行う必要がありますか? (それは通常どのように行われますか?)
  3. IoC コンテナーを使用するときに拡張ポイントを簡単に定義するにはどうすればよいですか?
4

2 に答える 2

5

おそらくMEFを見たいと思うでしょう。それはあなたが尋ねたすべてのことを可能にします。使用する用語 (ComposableParts、Exports など) は最初は混乱しますが、使用するのは非常に簡単です。

プラグイン自体が登録を行うための Register メソッドを提供するのは一般的ですか?

MEF は、プラグインを見つけて登録する作業をアプリケーションに実行させます。プラグインは、「私は X を実行できるプラグインです」というインターフェースを実装するだけで済みます。

IoC が登録を行う必要がありますか? (それは通常どのように行われますか?)

MEF プラグインを使用するアプリケーションは、プラグインのロード方法を指定できます。これは、ディレクトリで DLL を検索したり、構成ファイルを読み取ってアセンブリ名のリストを取得したり、GAC をチェックしたり、何でもかまいません。完全に拡張可能です (独自の検索クラスを作成できるという点で)

IoC コンテナーを使用するときに拡張ポイントを簡単に定義するにはどうすればよいですか?

MEF はインターフェイスを使用して、アプリケーションとプラグインの間のコントラクトを定義します。

于 2012-09-12T13:27:56.320 に答える
0

この回答は、私のコンテナに固有のものです。

現在のアプリケーションは、コンパイル時にアプリケーションに認識されていないさまざまな「プラグイン」/「拡張機能」の動的ロードと「フック」のサポートを開始する必要があります。

これを可能にするには、アプリケーションとすべてのプラグインの間で共有されるクラス ライブラリに配置するいくつかの拡張インターフェイスを定義する必要があります。

たとえば、アプリケーションがアプリケーション メニューに何かを追加できるようにしたい場合は、次のインターフェイスを作成できます。

class ApplicationMenu
{
    // The "File" menu
    IMenuItem File { get; }
}

interface IMenuRegistrar
{
    void Register(ApplicationMenu menu);
}

つまり、プラグインは次のクラスを作成できます。

[Component]
public class CoolPluginMenuRegistrar : IMenuRegistrar
{
    public void Register(ApplicationMenu menu)
    {
        menu.File.Add("mnuMyPluginMenuName", "Load jokes");
    }
}

この[Component]属性はコンテナによって使用され、クラスを検出して自動的に登録できるようにします。

上記のようなすべての拡張ポイントを登録するために必要なことは、次のとおりです。

public class Program
{
    public static void Main(string[] args)
    {
        var registrar = new ContainerRegistrar();
        registrar.RegisterComponents(Lifetime.Transient, Environment.CurrentDirectory, "MyApp.Plugin.*.dll");
        var container = registrar.Build();

        // all extension points have been loaded. To load all menu extensions simply do something like:

        var menu = GetMainMenu();
        foreach (var registrar in container.ResolveAll<IMenuRegistrar>())
        {
            registrar.Register(menu);
        }
    }
}

これらの拡張機能は、特定のクラスのイベント ハンドラーとして追加されるなど、アプリケーションのさまざまな領域に "フック" されます。私の知る限り、IoC コンテナーを使用すると、実行時にオブジェクトを動的に検出し、それらをコンテナーに登録できます。

うん。あなたはそれをすべて手に入れます。

IoC コンテナーは、さまざまなイベントにフックすることもできますか? それとも、そのようなフレームワークなしでこのタスクを実行する方が簡単ですか?

はい。イベントメカニズムが組み込まれています。イベント クラス (共有クラス ライブラリ内の通常の .NET クラス) を配置します。インターフェイスを実装することで、それらをサブスクライブするだけです。

[Component]
public class ReplyEmailNotification : ISubscriberOf<ReplyPosted>
{
    ISmtpClient _client;
    IUserQueries _userQueries;

    public ReplyEmailNotification(ISmtpClient client, IUserQueries userQueries)
    {
        _client = client;
        _userQueries = userQueries;
    }

    public void Invoke(ReplyPosted e)
    {
        var user = _userQueries.Get(e.PosterId);
        _client.Send(new MailMessage(user.Email, "bla bla"));
    }
} 

イベントを公開するには:

DomainEvent.Publish(new ReplyPosted(user.Id, "This is a subject"));

イベントは、次の条件を満たしている限り、任意のプラグインで処理できます。

  1. イベントクラスにアクセスできます
  2. コンテナに登録済み([Component]または手動登録)
  3. 道具ISubscriberOf<T>

プラグイン自体が登録を行うための Register メソッドを提供するのは一般的ですか?

うん。共有アセンブリの拡張ポイントとして定義されているさまざまなインターフェイスを介して。

IoC が登録を行う必要がありますか? (それは通常どのように行われますか?)

はい。コンテナがそれを提供する場合。

IoC コンテナーを使用するときに拡張ポイントを簡単に定義するにはどうすればよいですか?

詳細については、http: //www.codeproject.com/Articles/440665/Having-fun-with-Griffin-Containerを参照してください。

于 2012-09-12T14:56:48.217 に答える