読者です 読者をやめる 読者になる 読者になる

checkpoint

自分用のIT技術系ノートです。古い情報や間違っている情報もあるので注意。

リフレクションを使って(ジェネリック)メソッドを実行する

C# .NET
public static string TestMethod1(int input)
{
  return "Test Method 1 : " + input.ToString();
}

がProgramクラスにある場合、これをリフレクションを使って呼び出すには

var mi = typeof(Program).GetMethod("TestMethod1");
var ret = mi.Invoke(null, new object[] { 100 });

のように名前を文字列で指定してMethodInfoを取得後、Invokeします。
名前を文字列で指定しない場合、

var f = new Func<int, string>(Program.TestMethod1);
var ret = f.Method.Invoke(null, new object[] { 99 });

のように、一旦デリゲートにしてそのMethodプロパティからInvokeします。

ジェネリックの場合は、

public static string TestMethod2<T>(T input)
{
  return "Test Method 2 : " + input.ToString();
}

こんな感じのメソッドがあったとして、名前を文字列で指定してInvokeする方法は

var mi = typeof(Program).GetMethod("TestMethod2");
var gmi = mi.MakeGenericMethod(typeof(double));
var ret = gmi.Invoke(null, new object[] { 99.999d });

名前を文字列で指定せずにデリゲートから呼び出す際は少し面倒ですが、

// 型パラメータを適当に指定する
var f = new Func<int, string>(Program.TestMethod2<int>);
var gmd = f.Method.GetGenericMethodDefinition();
var gmi = gmd.MakeGenericMethod(typeof(double));
var ret = gmi.Invoke(null, new object[] { 99.999d });

のようにすればOK。

メソッドをそのまま呼び出せるのに、なぜわざわざリフレクションで呼ぶのか?
ジェネリックの型パラメータをTypeオブジェクトで指定したいからです。

(例えばひとつ上のコードでは、double型のTypeオブジェクトがあれば型パラメータにdoubleを指定して呼び出せるわけです。)