ジェネリック型のメソッドやジェネリックメソッドを呼び出す場合、引数リストの型はすべて具体的な型に型付けされている必要があります。 型付けされていない状態で呼び出した場合、例外InvalidOperationExceptionがスローされます。 そのため、引数リストにジェネリック型の型パラメータおよびジェネリックメソッドの型パラメータを含む場合は、呼び出す時点で何らかの具体的な型に型付け(置き換え)されている必要があります。
ジェネリック型(Type)ではType.MakeGenericTypeメソッド(関連:§.ジェネリック型の型情報)、ジェネリックメソッド(MethodInfo)ではMethodInfo.MakeGenericMethodメソッドを呼び出すことによって、型パラメータを具体的な型に置き換え、構築された(型付けされた)ジェネリック型・ジェネリックメソッドを取得することができます。
すべての型パラメータが具体的な型に型付けされた状態のMethodInfoでは、通常のMethodInfoと同様にInvokeメソッドで呼び出すことができます。
Type.InvokeMemberメソッドを使った呼び出しでは、具体的な型に型付けされないジェネリックメソッドを呼び出すと、例外MissingMethodExceptionがスローされます。
すべての型パラメータが型付けされているジェネリック型(ContainsGenericParametersプロパティがfalseのType)における、非ジェネリックなメソッド(型パラメータを取らないメソッド)は、通常のメソッドと同様に呼び出すことができます。
Type.InvokeMemberでジェネリック型のメソッド/ジェネリックメソッドを呼び出す
using System;
using System.Reflection;
// 型パラメータTCを取るジェネリック型
class C<TC> {
// ジェネリック型の型パラメータTCを引数にとるメソッド
public void M(TC tc) => Console.WriteLine($"M({typeof(TC)} = {tc})");
// ジェネリック型の型パラメータTCと、メソッドの型パラメータTMを引数にとるジェネリックメソッド
public void M<TM>(TC tc, TM tm) => Console.WriteLine($"M({typeof(TC)} = {tc}, {typeof(TM)} = {tm})");
}
class Sample {
static void Main()
{
// ジェネリック型定義(C<>)の型情報ではインスタンス作成・メソッド呼び出しはできない
// MakeGenericTypeメソッドで具体的な型(C<string>など)に型付けする必要がある
var t = typeof(C<>).MakeGenericType(typeof(string));
//var t = typeof(C<string>); // あるいは型付けされた状態の型情報を取得する
var inst = Activator.CreateInstance(t);
// メソッドC<string>.M(string)を呼び出す
t.InvokeMember("M", BindingFlags.InvokeMethod, null, inst, new object[] {"arg"});
// メソッドC<string>.M<int>(string, int)を呼び出したい
// (型引数TMは与えられた引数から自動的には型付けされないため、
// 引数リストと一致するメソッドを見つけられず、結果MissingMethodExceptionをスローする)
t.InvokeMember("M", BindingFlags.InvokeMethod, null, inst, new object[] {"arg", 42});
}
}
実行結果
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()