ソフトウェアで動的にロード可能なプラグインを作成する方法を提供したいと思います。これを行う一般的な方法は、LoadLibrary WinAPI関数を使用してdllをロードし、GetProcAddressを呼び出してそのdll内の関数へのポインターを取得することです。
私の質問は、C#/。Netアプリケーションでプラグインを動的にロードするにはどうすればよいですか?
ソフトウェアで動的にロード可能なプラグインを作成する方法を提供したいと思います。これを行う一般的な方法は、LoadLibrary WinAPI関数を使用してdllをロードし、GetProcAddressを呼び出してそのdll内の関数へのポインターを取得することです。
私の質問は、C#/。Netアプリケーションでプラグインを動的にロードするにはどうすればよいですか?
.NET 3.5の時点で、.NETアプリケーションからプラグインを作成およびロードするための形式化された組み込みの方法があります。それはすべてSystem.AddIn名前空間にあります。詳細については、MSDNのこの記事を確認してください:アドインと拡張性
Base
次のコードスニペット(C#)は、アプリケーションパスのクラスライブラリ(* .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);
}
}
}
編集:Mattによって参照されるクラスは、おそらく.NET3.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
いる . 詳細については、MSDN の Unloading AppDomains に関する記事を参照してください。
Windows Communication Framework (WCF) を使用してプラグイン フレームワークを作成する方法を説明するスタック オーバーフローの質問と回答があります。
私は 2 つのプラグイン フレームワークを知っています。
System.AddIn
た名前空間です。Managed Extensibility Framework (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 形式で利用できるManaged Extensibility Frameworkです。
基本的に、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名前空間と次のメソッドを確認してください。
最初にそのパスでアセンブリをロードし、次にその名前でアセンブリからタイプ(クラス)を取得し、次にその名前でクラスのメソッドを再度取得し、最後に関連するパラメーターを使用してメソッドを呼び出します。
この記事は少し古いですが、アプリケーション内に拡張レイヤーを作成する場合に引き続き適用できます。