6

.NET を使用してプラグイン システムを作成しようとしていますが、それが正しく行われているかどうかわかりません。システムの基本は、特定のディレクトリ ({apppath}/Plugins/) にプリコンパイル済みの DLL が多数あることです。特定の基本クラスを継承している場合は、リフレクションを使用してそれぞれを調べ、利用可能なすべてのクラスを調べたいと考えています。 (これはさらに別の DLL で定義されていますが、後で説明します)、そのインスタンスを作成し、そのインスタンスで特定の関数を呼び出します。

Public Sub ScanPluginsInDirectory(ByVal Directory As String)

    Dim Plugins As New IO.DirectoryInfo(Directory)
    Dim Files As IO.FileInfo() = Plugins.GetFiles("*.dll")
    Dim CryptType As Type = GetType(CryptPluginBase)
    Dim PluginsData as List(Of LoadedPluginsInfo)

    For Each DllFile As IO.FileInfo In Files
        Try
            Dim thisAsm As Assembly = Assembly.LoadFrom(DllFile.FullName)
            Dim ClassDefs = thisAsm.GetTypes().Where(Function(type) CryptType.IsAssignableFrom(type))

            For Each ClassDef As Type In ClassDefs
                Dim A As Object
                A = ClassDef.Assembly.CreateInstance(ClassDef.Name)
                PluginsData.Add(New LoadedPluginsInfo(A.Plugin(), False))
            Next
        Catch ex As Exception
            Continue For
        End Try
    Next
End Sub

私が抱えている特定の問題は、これが正しい方法かどうかわからないということです。A.Plugin()実際に存在し、ここで参照されている構造とクラスにバグがないと仮定できる場合、私がやろうとしている方法は機能しますか? 誰かが助けるためにさらにコードが必要な場合は、投稿できます。

4

2 に答える 2

3

全体として、戦略は機能するはずです。Assembly.LoadFrom呼び出しは、ターゲットアセンブリをプロセスにロードします。そこから、型検査を実行し、それらの型のインスタンスを作成することができます。

インスタンスを作成する最も簡単で信頼できる方法は、Activator.CreateInstanceメソッドを使用することだと思います。

For Each def As Type in ClassDefs
  Dim inst = Activator.CreateInstance(def)
  PluginsData.Add(new LoadedPluginsInfo(inst.Plugin(), False))
Next

目標に応じて、別の提案として、Try/Catchブロックをループから外すのではなくループに移動することもできます。ループの外側にTry/Catchブロックがあるということは、アセンブリ内の特定のタイプにエラーがある場合、そのアセンブリからすべてのタイプを破棄することを意味します。内部に移動すると、期待どおりに機能しないタイプのみを破棄できます。dただし、現在の動作が意図している可能性があります。

于 2009-04-12T20:06:17.767 に答える
1

これはうまくいくはずです、私は以前にいくつかのプロジェクトでこの種のものを使用していました。私は特にコンストラクターを探して呼び出しましたが、それ以外は同じ考えでした。

ただし、プラグインアーキテクチャ用に多くのことを処理するMEFを確認することをお勧めします(リリースバージョンを少し待つ場合は、今のところCTPのままです)。

于 2009-04-12T20:08:35.937 に答える