.NET にプラグインをロードするにはどうすればよいですか?
-
08-06-2019 - |
質問
ソフトウェアで動的にロード可能なプラグインを作成する何らかの方法を提供したいと考えています。これを行う一般的な方法は、 ロードライブラリ DLL をロードして呼び出すための WinAPI 関数 GetProcAddress その DLL 内の関数へのポインターを取得します。
私の質問は、C#/.Net アプリケーションにプラグインを動的にロードするにはどうすればよいですか?
解決
次のコード スニペット (C#) は、次のコードから派生した具象クラスのインスタンスを構築します。 Base
アプリケーション パスのクラス ライブラリ (*.dll) で見つかり、リストに保存されます。
using System.IO;
using System.Reflection;
List<Base> objects = new List<Base>();
DirectoryInfo dir = new DirectoryInfo(Application.StartupPath);
foreach (FileInfo file in dir.GetFiles("*.dll"))
{
Assembly assembly = Assembly.LoadFrom(file.FullName);
foreach (Type type in assembly.GetTypes())
{
if (type.IsSubclassOf(typeof(Base)) && type.IsAbstract == false)
{
Base b = type.InvokeMember(null,
BindingFlags.CreateInstance,
null, null, null) as Base;
objects.Add(b);
}
}
}
編集: によって参照されるクラス マット おそらく .NET 3.5 ではより良いオプションです。
他のヒント
プラグインの動的ロード
.NET アセンブリを動的にロードする方法については、「」を参照してください。 この質問 (そして 私の答え)。これは、ロードを作成するためのコードです。 AppDomain
そしてそこにアセンブリをロードします。
var domain = AppDomain.CreateDomain("NewDomainName");
var pathToDll = @"C:\myDll.dll";
var t = typeof(TypeIWantToLoad);
var runnable = domain.CreateInstanceFromAndUnwrap(pathToDll, t.FullName)
as IRunnable;
if (runnable == null) throw new Exception("broke");
runnable.Run();
プラグインのアンロード
プラグイン フレームワークの一般的な要件は、プラグインをアンロードすることです。動的にロードされたアセンブリをアンロードするには (例:プラグインとアドイン)を含むものをアンロードする必要があります AppDomain
. 。詳細については、を参照してください。 AppDomain のアンロードに関する MSDN のこの記事.
WCF の使用
があります スタックオーバーフローに関する質問と回答 Windows Communication Framework (WCF) を使用してプラグイン フレームワークを作成する方法について説明します。
既存のプラグイン フレームワーク
私は 2 つのプラグイン フレームワークを知っています。
- Mono.アドイン - で述べたように 別の質問に対するこの回答.
- マネージド アドイン フレームワーク (MAF) - これは
System.AddIn
としての名前空間 マットが答えの中で言及した.
について話す人もいます。 マネージド拡張性フレームワーク (MEF) プラグインまたはアドイン フレームワークとしてではありませんが、そうではありません。詳細については、を参照してください。 この StackOverflow.com の質問 そして この StackOverflow.com の質問.
実行中のコードには悪意がある可能性があるため、ヒントの 1 つは、すべてのプラグインなどを独自の AppDomain にロードすることです。独自の AppDomain を使用して、読み込みたくないアセンブリや型を「フィルター」することもできます。
AppDomain domain = AppDomain.CreateDomain("tempDomain");
アセンブリをアプリケーション ドメインにロードするには、次のようにします。
AssemblyName assemblyName = AssemblyName.GetAssemblyName(assemblyPath);
Assembly assembly = domain.Load(assemblyName);
アプリケーション ドメインをアンロードするには、次の手順を実行します。
AppDomain.Unload(domain);
はい、Matt と System.AddIn への ++ (System.AddIn に関する 2 部構成の MSDN マガジン記事が入手可能です) ここ そして ここ)。.NET Framework が将来どのような方向に進むかを知るために検討すべきもう 1 つのテクノロジは、 マネージド拡張性フレームワーク 現在、Codeplex で CTP 形式で入手できます。
基本的には 2 つの方法で実行できます。
1 つ目は、kernel32.dll をインポートし、前に使用したように LoadLibrary と GetProcAddress を使用することです。
[DllImport("kernel32.dll")]
internal static extern IntPtr LoadLibrary(String dllname);
[DllImport("kernel32.dll")]
internal static extern IntPtr GetProcAddress(IntPtr hModule, String procname);
2 つ目は、.NET の方法で実行することです。反射を利用することで。System.Reflection 名前空間と次のメソッドを確認してください。
まず、パスによってアセンブリを読み込み、次に名前によって型 (クラス) を取得し、次に名前によってクラスのメソッドを再度取得し、最後に関連するパラメーターを使用してメソッドを呼び出します。
この記事は少し古いものですが、アプリケーション内で拡張レイヤーを作成する場合にも適用できます。