ジェネリック型のメソッドやジェネリックメソッドを呼び出す場合、引数リストの型はすべて具体的な型に型付けされている必要があります。 型付けされていない状態で呼び出した場合、例外InvalidOperationExceptionがスローされます。 そのため、引数リストにジェネリック型の型パラメータおよびジェネリックメソッドの型パラメータを含む場合は、呼び出す時点で何らかの具体的な型に型付け(置き換え)されている必要があります。
ジェネリック型(Type)ではType.MakeGenericTypeメソッド(関連:§.ジェネリック型の型情報)、ジェネリックメソッド(MethodInfo)ではMethodInfo.MakeGenericMethodメソッドを呼び出すことによって、型パラメータを具体的な型に置き換え、構築された(型付けされた)ジェネリック型・ジェネリックメソッドを取得することができます。
すべての型パラメータが具体的な型に型付けされた状態のMethodInfoでは、通常のMethodInfoと同様にInvokeメソッドで呼び出すことができます。
Type.InvokeMemberメソッドを使った呼び出しでは、具体的な型に型付けされないジェネリックメソッドを呼び出すと、例外MissingMethodExceptionがスローされます。
すべての型パラメータが型付けされているジェネリック型(ContainsGenericParametersプロパティがfalseのType)における、非ジェネリックなメソッド(型パラメータを取らないメソッド)は、通常のメソッドと同様に呼び出すことができます。
Type.InvokeMemberでジェネリック型のメソッド/ジェネリックメソッドを呼び出す
Imports System
Imports System.Reflection
' 型パラメータTCを取るジェネリック型
Class C(Of TC)
' ジェネリック型の型パラメータTCを引数にとるメソッド
Public Overloads Sub M(ByVal _tc As TC)
Console.WriteLine($"M({GetType(TC)} = {_tc})")
End Sub
' ジェネリック型の型パラメータTCと、メソッドの型パラメータを引数TMにとるジェネリックメソッド
Public Overloads Sub M(Of TM)(ByVal _tc As TC, ByVal _tm As TM)
Console.WriteLine($"M({GetType(TC)} = {_tc}, {GetType(TM)} = {_tm})")
End Sub
End Class
Class Sample
Shared Sub Main()
' ジェネリック型定義(C(Of))の型情報ではインスタンス作成・メソッド呼び出しはできない
' MakeGenericTypeメソッドで具体的な型(C(Of String)など)に型付けする必要がある
Dim t As Type = GetType(C(Of)).MakeGenericType(GetType(String))
' Dim t As Type = GetType(C(Of String)) ' あるいは型付けされた状態の型情報を取得する
Dim inst As Object = Activator.CreateInstance(t)
' メソッドC(Of String).M(Of String)を呼び出す
t.InvokeMember("M", BindingFlags.InvokeMethod, Nothing, inst, New Object() {"arg"})
' メソッドC(Of String).M(Of Integer)(String, Integer)を呼び出したい
' (型引数TMは与えられた引数から自動的には型付けされないため、
' 引数リストと一致するメソッドを見つけられず、結果MissingMethodExceptionをスローする)
t.InvokeMember("M", BindingFlags.InvokeMethod, Nothing, inst, New Object() {"arg", 42})
End Sub
End Class
実行結果
M(System.String = arg) Unhandled exception. System.MissingMethodException: Method 'C`1[[System.String, System.Private.CoreLib, Version=5.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e]].M' not found. at System.RuntimeType.InvokeMember(String name, BindingFlags bindingFlags, Binder binder, Object target, Object[] providedArgs, ParameterModifier[] modifiers, CultureInfo culture, String[] namedParams) at System.Type.InvokeMember(String name, BindingFlags invokeAttr, Binder binder, Object target, Object[] args) at Sample.Main()