4

我们目前正在使用 .NET 3.5,我们的部分应用程序使用动态调用(使用MethodBase.Invoke

我想知道是否可以将命名参数(在.NET 4中)与动态调用混合,以执行类似于:

// Dictionary that holds parameter name --> object mapping
var parameters = new Dictionary<string, object>();

// Add parameters ....

// Invoke where each parameter will match the one from the method signature.
methodInfo.Invoke(obj, parameters);

是否有任何 API 允许此选项开箱即用?如果没有,是否有可能开发一些解决方案来执行此操作?

编辑:

重新考虑这个问题,这听起来类似于编译器实际上可能需要根据参数列表匹配方法调用。也许有一些编译器 API(或新的 Roslyn 项目)可以轻松做到这一点?(没有自己编码,可能容易出错)。

4

3 回答 3

17

你可以使用这样的代码:

public static class ReflectionExtensions {

    public static object InvokeWithNamedParameters(this MethodBase self, object obj, IDictionary<string, object> namedParameters) { 
        return self.Invoke(obj, MapParameters(self, namedParameters));
    }

    public static object[] MapParameters(MethodBase method, IDictionary<string, object> namedParameters)
    {
        string[] paramNames = method.GetParameters().Select(p => p.Name).ToArray();
        object[] parameters = new object[paramNames.Length];
        for (int i = 0; i < parameters.Length; ++i) 
        {
            parameters[i] = Type.Missing;
        }
        foreach (var item in namedParameters)
        {
            var paramName = item.Key;
            var paramIndex = Array.IndexOf(paramNames, paramName);
            if (paramIndex >= 0)
            {
                parameters[paramIndex] = item.Value;
            }
        }
        return parameters;
    }
}

然后这样称呼它:

var parameters = new Dictionary<string, object>();
// Add parameters ...
methodInfo.InvokeWithNamedParameters(obj, parameters);
于 2012-10-25T16:02:03.337 回答
1

您可以在本文的帮助下获取参数名称如何获取方法参数的名称?然后您可以重新排序它们以调用它们,如此处所述反射:如何使用参数调用方法

于 2012-10-25T15:31:23.293 回答
1

使用 .net4,我有一个开源框架 ImpromptuInterface(在 nuget 中找到),可以轻松使用 DLR api 进行后期调用,包括命名/可选参数

var result = Impromptu.InvokeMember(target, "MyMethod", parameters.Select(pair=>  InvokeArg.Create(pair.Key, pair.Value)).Cast<object>().ToArray());
于 2012-10-29T20:06:31.353 回答