ジェネリック型のメソッドやジェネリックメソッドでは型パラメータが引数として含まれる場合があり、引数リストを指定してメンバを取得する場合はそれを考慮する必要があります。

.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つを組み合わせて引数リストとして指定します。

ジェネリック型とジェネリックメソッドそれぞれの型パラメータを取得して、引数リストとして指定する .NET Standard 2.1/.NET Core 2.1
using System;
using System.Reflection;

// 2つの型パラメータTCx, TCyを取るジェネリック型
class C<TCx, TCy> {
  // ジェネリック型の型パラメータを引数にとるメソッド
  public void M(TCx tcx) {}
  public void M(TCx tcx, TCy tcy) {}
  // ジェネリック型の型パラメータと、メソッドの型パラメータを引数にとるジェネリックメソッド
  public void M<TMx>(TCx tcx, TMx tmx) {}
  public void M<TMx, TMy>(TCy tcy, TMx tmx, TMy tmy) {}
}

class Sample {
  static void Main()
  {
    var t = typeof(C<,>);

    // 引数リストが(TCx)のメソッドを取得する
    var m1 = t.GetMethod("M", types: new[] {
      t.GetGenericArguments()[0] // 型パラメータTCx(ジェネリック型C<,>の0番目の型パラメータ)
    });

    // 引数リストが(TCx, TCy)のメソッドを取得する
    var m2 = t.GetMethod("M", types: new[] {
      t.GetGenericArguments()[0], // 型パラメータTCx(ジェネリック型C<,>の0番目の型パラメータ)のType
      t.GetGenericArguments()[1]  // 型パラメータTCy(ジェネリック型C<,>の1番目の型パラメータ)のType
    });

    // 引数リストが(TCx, TMx)のメソッドを取得する
    var m3 = t.GetMethod("M",
      genericParameterCount: 1, // 型パラメータが1つのジェネリックメソッド
      types: new[] {
        t.GetGenericArguments()[0],         // 型パラメータTCx(ジェネリック型C<,>の0番目の型パラメータ)のType
        Type.MakeGenericMethodParameter(0)  // 型パラメータTMx(ジェネリックメソッドM<>の0番目の型パラメータ)のType
      }
    );

    // 引数リストが(TCy, TMx, TMy)のメソッドを取得する
    var m4 = t.GetMethod("M",
      genericParameterCount: 2, // 型パラメータが2つのジェネリックメソッド
      types: new[] {
        t.GetGenericArguments()[1],         // 型パラメータTCy(ジェネリック型C<,>の1番目の型パラメータ)のType
        Type.MakeGenericMethodParameter(0), // 型パラメータTMx(ジェネリックメソッドM<,>の0番目の型パラメータ)のType
        Type.MakeGenericMethodParameter(1)  // 型パラメータTMy(ジェネリックメソッドM<,>の1番目の型パラメータ)のType
      }
    );

    Console.WriteLine($"{nameof(m1)} = {m1}");
    Console.WriteLine($"{nameof(m2)} = {m2}");
    Console.WriteLine($"{nameof(m3)} = {m3}");
    Console.WriteLine($"{nameof(m4)} = {m4}");
  }
}
実行結果
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メソッドを使って候補となるメソッドの一覧を取得し、そこから該当するメソッドを探し出す必要があります。

MENTAにてテキストチャットによるサポートを行っています。 問題の解決法をお探しの方や.NET/C#を学習中の方はどうぞご利用ください。