ジェネリック型のメソッドやジェネリックメソッドでは型パラメータが引数として含まれる場合があり、引数リストを指定してメンバを取得する場合はそれを考慮する必要があります。
.NET Standard 2.1/.NET Core 2.1以降のType.GetMethodメソッドでは、型パラメータの数と引数リストを指定して特定のジェネリックメソッドを取得するためのオーバーロードが追加されています。
型パラメータT
をとるジェネリックメソッドを考えたとき、このT
に対応する型を引数リストに指定する場合は、Type.MakeGenericMethodParameterメソッドを使います。 このメソッドでは、型パラメータの位置を0から始まる値で指定することにより、その位置の型パラメータを表すTypeを返します。 例えば、型パラメータU
, V
の2つをとるジェネリックメソッドであれば、位置が0
ならU
、位置が1
ならV
の型パラメータを表すTypeを返します。
Imports System
Imports System.Reflection
Class C
Public Overloads Sub M(ByVal x As Integer)
End Sub
Public Overloads Sub M(Of T)(ByVal _t As T)
End Sub
Public Overloads Sub M(Of U, V)(ByVal _u As U, ByVal _v As V)
End Sub
End Class
Class Sample
Shared Sub Main()
Dim t As Type = GetType(C)
' メソッド名のみでは対象が限定できないため、AmbiguousMatchExceptionとなる
'Dim ma As MethodInfo = t.GetMethod("M")
' 引数リストが(Integer)のメソッドMを取得する
Dim m1 As MethodInfo = t.GetMethod("M", New Type() {GetType(Integer)})
' 引数リストが(Long)のメソッドMを取得しようとする
' M(Of T)のTをLongに型付けしたものが取得されるのではなく、M(Long)を取得しようとするが、存在しないため、Nothingが返される
Dim m2 As MethodInfo = t.GetMethod("M", New Type() {GetType(Long)})
' 型パラメータTをとり、引数リストが(T)のメソッドMを取得する
' GetMethodの引数genericParameterCountに型パラメータの数として1を指定し、
' 引数リストtypesにはType.MakeGenericMethodParameterメソッドで0番目の型パラメータに対応する型を作成して指定する
Dim m3 As MethodInfo = t.GetMethod(
"M", ' 名前が"M"のメソッドを対象とする
genericParameterCount := 1, ' 型パラメータの数が1のものを対象とする
types := New Type() {
Type.MakeGenericMethodParameter(0) ' Type.MakeGenericMethodParameterメソッドで0番目の型パラメータ(T)を表す型を作成して、引数リストとして指定する
}
)
' 型パラメータU, Vをとり、引数リストが(U, V)のメソッドMを取得する
Dim m4 As MethodInfo = t.GetMethod(
"M", ' 名前が"M"のメソッドを対象とする
genericParameterCount := 2, ' 型パラメータの数が2のものを対象とする
types := New Type() {
Type.MakeGenericMethodParameter(0), ' 0番目の型パラメータ(U)を表す型
Type.MakeGenericMethodParameter(1) ' 1番目の型パラメータ(V)を表す型
}
)
Console.WriteLine($"{NameOf(m1)} = {m1}")
Console.WriteLine($"{NameOf(m2)} = {m2}")
Console.WriteLine($"{NameOf(m3)} = {m3}")
Console.WriteLine($"{NameOf(m4)} = {m4}")
End Sub
End Class
m1 = Void M(Int32) m2 = m3 = Void M[T](T) m4 = Void M[U,V](U, V)
さらに、ジェネリック型のジェネリックメソッドでは、ジェネリック型の型パラメータ(class C<TC>
のTC
)と、ジェネリックメソッドの型パラメータ(void M<TM>()
のTM
)の2種類が引数に含まれる場合があります。
ジェネリック型の型パラメータはType.GetGenericArgumentsメソッドで取得することができ、ジェネリックメソッドの型パラメータはType.MakeGenericMethodParameterメソッドで得られるTypeで表すことができるため、この2つを組み合わせて引数リストとして指定します。
ジェネリック型のメソッド・ジェネリックメソッドのMethodInfoを使ってメソッド呼び出しを行う方法については§.ジェネリック型のメソッド・ジェネリックメソッドを参照してください。
Typeが型パラメータを表すものかどうか、またTypeがジェネリック型の型パラメータか、ジェネリックメソッドの型パラメータかどうかを判別する方法については§.型パラメータの分類を参照してください。
Type.MakeGenericMethodParameterを使用することができない.NET Standard 2.1/.NET Core 2.1より前やそれ以外の環境では、Type.GetMethodsメソッドを使って候補となるメソッドの一覧を取得し、そこから該当するメソッドを探し出す必要があります。