3

在我的项目中,我有以下两种方法,它们用于调用具有可变数量和参数类型的其他方法:

 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 实现相同的功能?如何将变量数量的参数传递给它以及如何获取参考值?

4

0 回答 0