アプリケーション (*.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 を使った。