Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/295.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 使用命名参数动态调用方法_C#_.net_Reflection_Named Parameters_Roslyn - Fatal编程技术网

C# 使用命名参数动态调用方法

C# 使用命名参数动态调用方法,c#,.net,reflection,named-parameters,roslyn,C#,.net,Reflection,Named Parameters,Roslyn,我们目前正在使用.NET3.5,部分应用程序使用动态调用(使用) 我想知道是否可以将命名参数(在.NET 4中)与动态调用混合在一起,以执行类似的操作: // Dictionary that holds parameter name --> object mapping var parameters = new Dictionary<string, object>(); // Add parameters .... // Invoke where each paramete

我们目前正在使用.NET3.5,部分应用程序使用动态调用(使用)

我想知道是否可以将命名参数(在.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);
//保存参数名称-->对象映射的字典
var参数=新字典();
//添加参数。。。。
//调用,其中每个参数将与方法签名中的参数匹配。
调用(对象,参数);
是否有任何API允许此选项开箱即用?如果没有,是否可以开发一些解决方案来执行此操作

编辑:


重新思考这个问题,它听起来类似于编译器可能实际需要如何根据参数列表匹配方法调用。也许有一些编译器API(或新的Roslyn项目)可以轻松地实现这一点?(无需自己编写,可能会出错)。

您可以在本文的帮助下获取参数名称,然后可以按照此处所述对其重新排序以调用它们。

您可以使用如下代码:

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);
公共静态类ReflectionExtensions{
公共静态对象调用WithNamedParameters(此MethodBase self、object obj、IDictionary namedParameters){
返回self.Invoke(对象,映射参数(self,namedParameters));
}
公共静态对象[]映射参数(MethodBase方法,IDictionary namedParameters)
{
string[]paramNames=method.GetParameters().Select(p=>p.Name.ToArray();
object[]parameters=新对象[paramNames.Length];
对于(int i=0;i=0)
{
参数[paramIndex]=项值;
}
}
返回参数;
}
}
然后这样称呼它:

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);
var参数=新字典();
//添加参数。。。
methodInfo.InvokeWithNamedParameters(对象,参数);

对于.net4,我有一个开源框架ImpromptuInterface(可以在nuget中找到),它使DLR API的使用变得简单

var result=Impromptu.InvokeMember(目标,“MyMethod”,参数.Select(pair=>InvokeArg.Create(pair.Key,pair.Value)).Cast().ToArray();

如果该方法使用默认参数值(.NET 4功能),会发生什么情况?这种解决方案在这种情况下有效吗?(它能否区分传递的空参数和不应传递的参数(并因此采用默认值)?我不确定,但我将使用代码并进行测试!@lysergic acid:寻找一些想法。太棒了,所以基本上我可以修改您的示例以反映这些属性,并在任何情况下将默认值放入数组中。谢谢!我已更改代码以使用
类型初始化参数。缺少
以考虑可选参数。但是我还没有测试它,请检查它是否有效。在设置值以防止
索引自动失效异常
之前,您可能需要检查
参数索引!=-1