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