.NET: プラグイン機構を実装するには

アプリケーション (*.exe) と同じディレクトリにサブディレクトリ "plugins" があって、その中にプラグインを放り込むと認識される、というパターン。
とりあえずプラグインのファイルは *.dll にして、その中から、指定したインタフェースを実装してるクラスを取り出すことにした。
SPI 用の dll を作ってインタフェースを入れておき、exe とプラグイン dll から参照する。
指定されたパスでプラグイン探索をやるメソッドはこんな感じ (例外処理省略)。PluginInterface.IPlugin がプラグイン用のインタフェース。

using System;
using System.IO;
using System.Reflection;
using System.Collections;

using PluginInterface;
private static IPlugin[] LoadPlugins(string path)
{
    Type it = typeof(IPlugin);
    
    ArrayList list = new ArrayList();
    foreach (string dll in Directory.GetFiles(path, "*.dll"))
    {
        Assembly a = Assembly.LoadFile(dll);
        foreach (Type t in a.GetTypes())
        {
            if (it.IsAssignableFrom(t))
            {
                list.Add(t.GetConstructor(Type.EmptyTypes).Invoke(null));
            }
        }
    }
    return (IPlugin[])list.ToArray(it);
}

実行時には、exe と同じディレクトリに SPI の dll を置く。プラグイン dll からも参照されるが、exe が読み込まれた時点で一緒に読み込まれるので、プラグイン格納用のディレクトリに SPI の dll を入れる必要はない。

関連ページ

探してみると、みんな同じようなことやってるみたい。日本語で一番情報量多いのはここかな。

DOBON.NET - プラグイン機能を持つアプリケーションを作成する
http://dobon.net/vb/dotnet/programing/plugin.html

メモ

型をあらわす System.Type には、IsSubclassOf というメソッドがあるが、これは、インタフェースを実装しているかどうかの確認には使えない。上では IsAssignableFrom を使った。