たきるブログ

C#やOracleなどの情報を書いています。

【VB】動的にクラスをロードして、文字列でメソッドを指定して実行する

@IT - 文字列で指定したクラスのインスタンスを作成するには?
@IT - 文字列で指定したメソッドを呼び出すには?
@IT - メソッドやプロパティの有無を確認して呼び出すには?

 
この記事を参考に、動的にクラスをロードして、文字列でメソッドを指定して実行する処理を書いてみる。

 
20111213_001.zip

Loader.vb

Imports System.Reflection
''' <summary>
''' クラスロード制御クラス
''' </summary>
''' <remarks>クラスの動的ロードに関する制御を行います。</remarks>
Public Class Loader
    ''' <summary>
    ''' コンストラクタ
    ''' </summary>
    ''' <remarks>外部からのインスタンス化は行えません。</remarks>
    Private Sub New()

    End Sub
    ''' <summary>
    ''' クラスロード処理
    ''' </summary>
    ''' <param name="className">クラス名</param>
    ''' <param name="filePath">クラスを有するDLLパス</param>
    ''' <returns>
    ''' 成功時:Typeオブジェクト<br />
    ''' 失敗時:Nothing
    ''' </returns>
    ''' <remarks>指定されたクラスのロード処理を行います。</remarks>
    Public Shared Function loadClass(ByVal className As String, Optional ByVal filePath As String = Nothing) As Type
        Dim classType As Type

        classType = Type.GetType(className)

        'アセンブリにロードされていない場合はDLLをロードする
        If classType Is Nothing Then
            If System.IO.File.Exists(filePath) = False Then
                Return classType
            End If

            Dim asm As Assembly = Assembly.LoadFrom(filePath)
            classType = asm.GetType(className)
            If classType Is Nothing Then
                asm = Nothing
            End If
        End If

        Return classType
    End Function
End Class

MyClass1.vb

Public Class MyClass1
    Public Sub testMethod1()
        System.Windows.Forms.MessageBox.Show("DLLのtestMethod()が呼び出されました")
    End Sub
End Class

Window1.vb

Public Class Window1
    Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
        'クラスのロード
        Dim classType As Type = Loader.loadClass("ClassLibrary1.MyClass1", System.IO.Directory.GetCurrentDirectory() & "\..\..\..\ClassLibrary1\bin\Debug\ClassLibrary1.dll")
        If classType Is Nothing Then
            Return
        End If
        Dim classInstance As Object = Nothing
        Try
            '通常のインスタンス化
            classInstance = Activator.CreateInstance(classType)

            '指定メソッド名の実行
            Dim mi As Reflection.MethodInfo = (classInstance.GetType()).GetMethod("testMethod")
            mi.Invoke(classInstance, Nothing)

        Catch ex As InvalidCastException
            'キャスト失敗
            classInstance = Nothing

        Catch ex As MissingMemberException
            '引数なしコンストラクタの存在がない
            classInstance = Nothing

        End Try
    End Sub
End Class

loadClass()の第一引数には、名前空間を含むクラス名を指定すれば良い。
第二引数はDLLのフルパス。
そもそもDLLが既にロードされている場合は、Type.GetType("名前空間.クラス名, アセンブリ名")という指定になるので、使い方間違ってんな俺。


インターフェースを実装しているかどうかをチェックしたいならば、Typeクラス内のGetInterface()で取得できるかどうかを検証すればいいようだ。
ただ、どうも散々調べてみたけど、『特定のクラスを継承しているかどうか』を検証する方法が見つからなかった・・・。

ご存知の方は是非pleeeeeeeeeeez!!