リフレクションを使用してメソッドを呼び出す場合、次の例外が発生する可能性があります:
この例外は単純です。正しい数のパラメーターを MethodInfo.Invoke() に渡していません。
この記事では、リフレクションの使用時にこの例外に遭遇する可能性のある 3 つの異なるケースを示します。
リフレクションを使用してメソッドを呼び出す
最も単純なケースは、メソッドを呼び出していて、単純にすべてのパラメーターを渡していない場合です。メソッド定義が変更されたか、単にパラメータの 1 つが省略されている可能性があります。この間違いは、コンパイラでは見つけられないため、簡単に犯してしまいます。
2 つの整数の合計を返す次のメソッドがあるとします:
public class Util
{
public int Add(int a, int b)
{
return a + b;
}
}
Code language: C# (cs)
次のコードは、リフレクションを使用してこのメソッドを呼び出します:
Util util = new Util();
int a = 1;
int b = 2;
var method = util.GetType().GetMethod("Add");
var parameters = new object[] { a };
var sum = method.Invoke(util, parameters);
Code language: C# (cs)
Util.Add() メソッドには、a と b の 2 つのパラメーターがあります。このコードはパラメーターの 1 つ (a) のみを渡しているため、TargetParameterCountException がスローされます。
解決策は簡単です。すべてのパラメーターを渡します。この場合、単純に b を渡す必要があります。
Util util = new Util();
int a = 1;
int b = 2;
var method = util.GetType().GetMethod("Add");
var parameters = new object[] { a, b };
var sum = method.Invoke(util, parameters);
Code language: C# (cs)
リフレクションを使用してデフォルト パラメータでメソッドを呼び出す
デフォルトのパラメーターは、リフレクションと同じようには機能しません。デフォルト パラメーターを持つメソッドがあり、リフレクションでそれを呼び出そうとする場合、デフォルトかどうかにかかわらず、すべてのパラメーターを渡す必要があります。
次のコードは、2 つの整数を減算し、差を返します。デフォルトのパラメーター b があります。
public class Util
{
public int Subtract(int a, int b = 0)
{
return a - b;
}
}
Code language: C# (cs)
次のコードは、リフレクションを使用してこのメソッドを呼び出します。パラメータの 1 つだけを渡しています。
Util util = new Util();
int a = 1;
int b = 2;
var method = util.GetType().GetMethod("Subtract");
var parameters = new object[] { a };
var difference = method.Invoke(util, parameters);
Code language: C# (cs)
Util.Subtract() には、a と b の 2 つのパラメーターが必要です。渡されるパラメーターは 1 つだけです – a – そのため、これが TargetParameterCountException をスローする理由です。
でも待ってください、これにはデフォルトのパラメータがありませんか?はい。ただし、デフォルトのパラメータは基本的にリフレクションでは機能しません。デフォルトのパラメータであっても、すべてのパラメータを渡す必要があります。
解決策は簡単です。両方のパラメータを渡します:
Util util = new Util();
int a = 1;
int b = 2;
var method = util.GetType().GetMethod("Subtract");
var parameters = new object[] { a, b };
var difference = method.Invoke(util, parameters);
Code language: C# (cs)
リフレクションを使用して拡張メソッドを呼び出す
拡張メソッドは単なる静的メソッドです。メソッドは 1 つの静的クラスで定義され、別の型で呼び出されます。ご想像のとおり、リフレクションで拡張メソッドを呼び出すときは、通常とは異なる方法で行う必要があります。
次の拡張メソッドがあるとします:
public static class Util
{
public static int Multiply(this int a, int b)
{
return a * b;
}
}
Code language: C# (cs)
リフレクションがなければ、次のように呼び出します:
a.Multiply(b);
Code language: C# (cs)
リフレクションを使用すると、次のように呼び出すことができます:
int a = 6;
int b = 3;
var method = typeof(Util).GetMethod("Multiply", BindingFlags.Static | BindingFlags.Public);
var parameters = new object[] { a, b };
var product = method.Invoke(null, parameters);
Code language: C# (cs)
まず、リフレクションを使用して静的メソッドを呼び出す場合、Invoke() の最初のパラメーターは null です。これは、インスタンスで呼び出していないためです。
次に、強調表示された行でわかるように、すべてのパラメーターを渡す必要があります (既定のパラメーターがある場合と同様)。それ以外の場合は、TargetParameterCountException がスローされます。