私のプロジェクトには、変数の数と型の引数を持つ他のメソッドを呼び出すために使用される次の 2 つのメソッドがあります。
private static object InvokeMethod(MethodInfo method, MyTargetClass target, object[] initialArgs, object[] additionalArgs)
{
object result = null;
var methodParams = method.GetParameters();
if (methodParams.Length == 0)
{
result = method.Invoke(target, null);
}
else
{
var args = CollectArguments(method, initialArgs, paramArgs);
// collect arguments with default values for missing ones and invoke the method
result = method.Invoke(target,args);
}
return result;
}
private static object[] CollectArguments(MethodInfo method, object[] initialArgs, object[] paramArgs)
{
List<object> allArgs = new List<object>();
allArgs.AddRange(initialArgs);
// append all param style args
if (paramArgs != null)
allArgs.AddRange(paramArgs);
// do we have enough arguments?
int missing = method.GetParameters().Length - allArgs.Count;
if (missing < 0)
throw new InvalidOperationException(string.Format("Too many arguments passed to the method {0}", method.Name));
for (int i = 0; i < missing; i++)
{
// all parameters after mandatory should be with optional default values, so pass them
allArgs.Add(Type.Missing);
}
return allArgs.ToArray();
}
InvokeMethod が頻繁に呼び出されるので、最適化したいと思います。私はすでに MethodInfo 参照をキャッシュしています。呼び出すすべてのメソッドにはカスタム属性があり、アプリケーションの起動時にこれらのメソッドを辞書に収集します。MyTargetClass 派生クラスのコンストラクターのラムダ式をキャッシュすることができましたが、メソッド呼び出しのラムダ式もキャッシュしたいと考えています。
Expression.Call のラムダ式を作成する方法の例をいくつか見つけましたが、問題は、デフォルト値も含む変数引数を処理する方法がわからないことです (そのため、Type.Missing を追加しています)。参照引数である可能性があります。
呼び出したいメソッドには追加のルールがいくつかありますが (簡潔にするために省略します)、基本的にメソッドは次のようになります。
MyMethod1(int a, long b = 2)
MyMethod2(ref long a, ref long b, string something)
ref 引数を使用する特殊なケースは常に知っているので、method.Invoke の後で ref 変数を収集します。
a = (long)allArgs[0];
b = (long)allArgs[1];
a と b は、外部から ref によって渡されます。
Expression.Call を使用して同じ機能を実現するにはどうすればよいですか? 引数の変数カウントを渡すにはどうすればよいですか? また、ref 値を取得するにはどうすればよいですか?