C# でアプリにプラグイン機能を作ることを考えています。
その中で、ServiceCollection をプラグイン側に渡して処理できない問題に対してリフレクションで挑むことを考えています。
で、手軽に何も考えなくても使えるライブラリ化して試しているのですが、そのアップデートをしました。
■ 何をアップデートしたか。
拡張メソッドを 2 つだけしか対応していなかったものを、オーバーロード含め該当の 2 クラス分のメソッド全部定義しました。
単純なコードの繰り返しですが、リフレクションのためデバッグしづらく、できるだけコピペで済む文字数をどう増やすかにも頭を悩ませ、丸 2 日分くらい時間使いました。
■ このライブラリは、こう使う!
アプリケーション側のコード。
pluginPath でプラグインの DLL を置く場所を設定しています。
PluginLoadContext.Invoke(services, method, null, null); でプラグイン内のメソッドを実行します。
var pluginPath = Path.Combine(Assembly.GetEntryAssembly()?.Location!, "../../../../../TestPlugin/bin/Debug/net10.0"); var plugins = PluginLoadContext.LoadExtensions(pluginPath); foreach (var plugin in plugins) foreach (var assembly in plugin.Assemblies) foreach (var type in assembly.GetTypes()) { var method = type.GetMethod("ConfigureServices"); if (method != null) { var result = PluginLoadContext.Invoke(services, method, null, null); Debug.Write(result); } }
プラグイン側のコード。
object 型でもらったオブジェクトに対して PluginServiceCollection のメソッドを実行します。
public class Class1 { public static string ConfigureServices(object services) { var r01 = PluginServiceCollection.AddHttpClient<ITest, Test>(services, F01)?.ToString(); var r02 = PluginServiceCollection.AddScoped(services, F02)?.ToString(); return string.Join(", ", r02, r02); } static Test F01(HttpClient httpClient) => new Test(); static Test F02(IServiceProvider serviceProvider) => new Test(); }
プラグインの DLL を pluginPath の場所に置きます。
これだけです。プラグイン側に、ServiceCollection の拡張機能のアセンブリは必要ありません。アプリケーション側のものがリフレクションされるので。