C# 使用反射调用函数,该反射具有;“参数”;参数(MethodBase)

C# 使用反射调用函数,该反射具有;“参数”;参数(MethodBase),c#,reflection,parameters,mono,C#,Reflection,Parameters,Mono,我有两个函数的MethodBase: public static int Add(params int[] parameters) { /* ... */ } public static int Add(int a, int b) { /* ... */ } 我有一个函数,通过我创建的类调用MethodBase: MethodBase Method; object Target; public object call(params object[] input) { return Me

我有两个函数的MethodBase:

public static int Add(params int[] parameters) { /* ... */ }
public static int Add(int a, int b) { /* ... */ }
我有一个函数,通过我创建的类调用MethodBase:

MethodBase Method;
object Target;
public object call(params object[] input)
{
    return Method.Invoke(Target, input);
}
现在如果我
AddTwoMethod.call(5,4)工作正常

如果我使用
AddMethod.call(5,4)返回:

未处理的异常:System.Reflection.TargetParameterCountException:参数与签名不匹配


有没有办法使这两个调用都能正常工作,而无需手动将参数放入
参数int[]
的数组中?

您应该将参数包装在数组中,但编译器会感到困惑,因此您需要帮助它:

例如:


您可以修改
调用
方法来检测params参数,并将其余输入转换为新数组。这样,您的方法的行为与应用于方法调用的逻辑C#几乎相同

我为您快速构建了一些东西(请注意,我以非常有限的方式测试了此方法,因此可能仍然存在错误):

公共对象调用(参数对象[]输入)
{
ParameterInfo[]parameters=Method.GetParameters();
bool hasParams=false;
如果(parameters.Length>0)
hasParams=parameters[parameters.Length-1]。GetCustomAttributes(typeof(paramaryattribute),false)。长度>0;
if(hasParams)
{
int lastParamPosition=parameters.Length-1;
object[]realParams=新对象[parameters.Length];
对于(int i=0;i

请注意,我以非常有限的方式测试了此方法,因此可能仍然存在错误。

假设我们有以下示例类:

public class Test
{
    public static int Add(int i1, int i2)
    {
        return i1 + i2;
    }

    public static int Add(params int[] ints)
    {
        int sum = 0;
        foreach (int i in ints)
            sum += i;

        return sum;
    }
}
要为静态
Add
方法的每个重载获取
MethodInfo
对象,应执行以下操作:

 MethodInfo Add2Ints = typeof(Test).GetMethod("Add",  new Type[] { typeof(int), typeof(int) });
 MethodInfo AddParamsInts = typeof(Test).GetMethod("Add", new Type[] { typeof(int[]) });
要调用这两个方法中的任何一个,请同时传递具有所调用的特定重载所期望的确切类型的参数:

 Add2Ints.Invoke(null, new object[] { 1, 2 });
 AddParamsInts.Invoke(null, new object[] { new int[] { 1, 2 } });
请注意,以下操作不起作用:

 AddParamsInts.Invoke(null, new object[] { 1, 2 }); 
因为
AddParmsInt
的签名实际上是
(int[])
,尽管出于礼貌,编译器允许您在引擎盖下调用
(int,int)
这样的方法,但真正发生的是,您在调用站点上的调用被转换为等价的
(int[])
调用。通过反射,您没有编译器的“帮助”,因此需要传递由方法签名定义的确切参数类型

综上所述,您的
调用
方法应如下所示:

 public object call(params object[] input)
 {
     return AddParamsInts.Invoke(null /*static*/, new object[] { input.Cast<int>().ToArray() });
 }

这导致System.ArgumentException:在尝试调用时无法转换参数。非常感谢,我没有考虑过获取自定义属性和测试类似的参数@布拉姆:你可以用反思的方式来做。请参阅我的答案,了解与您尝试的更相似的替代方法。就我个人而言,我认为这个解决方案太复杂了,无法满足您的需要。
call
方法可以用一行代码来解决。我觉得你的建议太复杂了,完全没有必要。更多信息请参见我的答案。我了解反射是如何工作的,我想知道是否有可能有一个调用方法可以像我标记的正确答案那样工作。与您的call方法类似,但不是专门针对params int[]函数,另一个call方法实际上适用于任何函数方法。假设我创建了一个
Print(字符串格式,params object[]vars)
函数,他的方法可以通过
PrintMethod.call正确调用它(“a+B:{0},a-B:{1}”,a+B,a-B)好,明白了。但很难从你的原始问题中看出这一点;)。
 AddParamsInts.Invoke(null, new object[] { 1, 2 }); 
 public object call(params object[] input)
 {
     return AddParamsInts.Invoke(null /*static*/, new object[] { input.Cast<int>().ToArray() });
 }
 public int Add(int i1, int i2) { }
 public int Add(int i1, int i2, params int[] args) { }