在我的项目中,我有以下两种方法,它们用于调用具有可变数量和参数类型的其他方法:
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 派生类的构造函数缓存 lambda 表达式,现在我还想为方法调用缓存 lambda 表达式。
我找到了一些如何为 Expression.Call 创建 lambda 表达式的示例,但问题是我不知道如何处理变量参数,其中还包括默认值(这就是我添加 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 实现相同的功能?如何将变量数量的参数传递给它以及如何获取参考值?