ジェネリック型のメソッドやジェネリックメソッドでは型パラメータが引数として含まれる場合があり、引数リストを指定してメンバを取得する場合はそれを考慮する必要があります。
.NET Standard 2.1/.NET Core 2.1以降のType.GetMethodメソッドでは、型パラメータの数と引数リストを指定して特定のジェネリックメソッドを取得するためのオーバーロードが追加されています。
型パラメータT
をとるジェネリックメソッドを考えたとき、このT
に対応する型を引数リストに指定する場合は、Type.MakeGenericMethodParameterメソッドを使います。 このメソッドでは、型パラメータの位置を0から始まる値で指定することにより、その位置の型パラメータを表すTypeを返します。 例えば、型パラメータU
, V
の2つをとるジェネリックメソッドであれば、位置が0
ならU
、位置が1
ならV
の型パラメータを表すTypeを返します。
using System;
using System.Reflection;
class C {
public void M(int i) {}
public void M<T>(T t) {}
public void M<U, V>(U u, V v) {}
}
class Sample {
static void Main()
{
var t = typeof(C);
// メソッド名のみでは対象が限定できないため、AmbiguousMatchExceptionとなる
//var ma = t.GetMethod("M"));
// 引数リストが(int)のメソッドMを取得する
var m1 = t.GetMethod("M", new[] {typeof(int)});
// 引数リストが(long)のメソッドMを取得しようとする
// M<T>のTをlongに型付けしたものが取得されるのではなく、M(long)を取得しようとするが、存在しないため、nullが返される
var m2 = t.GetMethod("M", new[] {typeof(long)});
// 型パラメータTをとり、引数リストが(T)のメソッドMを取得する
// GetMethodの引数genericParameterCountに型パラメータの数として1を指定し、
// 引数リストtypesにはType.MakeGenericMethodParameterメソッドで0番目の型パラメータに対応する型を作成して指定する
var m3 = t.GetMethod(
"M", // 名前が"M"のメソッドを対象とする
genericParameterCount: 1, // 型パラメータの数が1のものを対象とする
types: new[] {
Type.MakeGenericMethodParameter(0) // Type.MakeGenericMethodParameterメソッドで0番目の型パラメータ(T)を表す型を作成して、引数リストとして指定する
}
);
// 型パラメータU, Vをとり、引数リストが(U, V)のメソッドMを取得する
var m4 = t.GetMethod(
"M", // 名前が"M"のメソッドを対象とする
genericParameterCount: 2, // 型パラメータの数が2のものを対象とする
types: new[] {
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}");
}
}
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メソッドを使って候補となるメソッドの一覧を取得し、そこから該当するメソッドを探し出す必要があります。