27

ソフトウェアで動的にロード可能なプラグインを作成する方法を提供したいと思います。これを行う一般的な方法は、LoadLibrary WinAPI関数を使用してdllをロードし、GetProcAddressを呼び出してそのdll内の関数へのポインターを取得することです。

私の質問は、C#/。Netアプリケーションでプラグインを動的にロードするにはどうすればよいですか?

4

8 に答える 8

28

.NET 3.5の時点で、.NETアプリケーションからプラグインを作成およびロードするための形式化された組み込みの方法があります。それはすべてSystem.AddIn名前空間にあります。詳細については、MSDNのこの記事を確認してください:アドインと拡張性

于 2008-08-18T08:07:21.047 に答える
20

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のより良いオプションです。

于 2008-08-18T07:41:24.390 に答える
8

プラグインの動的ロード

.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 に関する記事を参照してください。

WCF の使用

Windows Communication Framework (WCF) を使用してプラグイン フレームワークを作成する方法を説明するスタック オーバーフローの質問と回答があります。

既存のプラグイン フレームワーク

私は 2 つのプラグイン フレームワークを知っています。

Managed Extensibility Framework (MEF)をプラグインまたはアドイン フレームワークと呼ぶ人もいますが、そうではありません。詳細については、この StackOverflow.com の質問この StackOverflow.comの質問 を参照してください。

于 2013-01-06T18:56:30.023 に答える
5

実行中のコードは潜在的に悪意がある可能性があるため、1つのヒントはすべてのプラグインなどを独自のAppDomainにロードすることです。独自のAppDomainを使用して、ロードしたくないアセンブリとタイプを「フィルタリング」することもできます。

AppDomain domain = AppDomain.CreateDomain("tempDomain");

そして、アセンブリをアプリケーションドメインにロードするには:

AssemblyName assemblyName = AssemblyName.GetAssemblyName(assemblyPath);
Assembly assembly = domain.Load(assemblyName);

アプリケーションドメインをアンロードするには:

AppDomain.Unload(domain);
于 2008-08-18T08:09:40.527 に答える
4

はい。Matt と System.AddIn への ++ (System.AddIn に関する 2 部構成の MSDN マガジン記事は、こちらこちらで入手できます)。.NET Framework が将来どこに向かっているのかを理解するために検討したいもう 1 つのテクノロジは、現在 Codeplex で CTP 形式で利用できるManaged Extensibility Frameworkです。

于 2008-09-09T22:03:07.717 に答える
3

基本的に、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名前空間と次のメソッドを確認してください。

最初にそのパスでアセンブリをロードし、次にその名前でアセンブリからタイプ(クラス)を取得し、次にその名前でクラスのメソッドを再度取得し、最後に関連するパラメーターを使用してメソッドを呼び出します。

于 2008-08-18T07:44:55.757 に答える
2

この記事は少し古いですが、アプリケーション内に拡張レイヤーを作成する場合に引き続き適用できます。

ユーザーがマクロとプラグインを使用して .NET アプリケーションに機能を追加できるようにする

于 2008-08-18T18:32:17.807 に答える