使用具有“params”参数的reflection调用函数(MethodBase)
我有两个函数的MethodBases:
public static int Add(params int[] parameters) { /* ... */ } public static int Add(int a, int b) { /* ... */ }
我有一个通过我制作的类调用MethodBases的函数:
MethodBase Method; object Target; public object call(params object[] input) { return Method.Invoke(Target, input); }
现在,如果我AddTwoMethod.call(5, 4);
它工作正常。
但是,如果我使用AddMethod.call(5, 4);
它返回:
未处理的exception:System.Reflection.TargetParameterCountException:参数与签名不匹配
是否有任何方法可以使两个调用都正常工作而无需手动将参数放入数组中用于params int[]
?
您可以修改call
方法以检测params参数并将其余输入转换为新数组。 这样,您的方法可以与C#应用于方法调用的逻辑非常相似。
我为你精心构建的东西(请注意我以非常有限的方式测试了这个方法,所以可能还有错误):
public object call(params object[] input) { ParameterInfo[] parameters = Method.GetParameters(); bool hasParams = false; if (parameters.Length > 0) hasParams = parameters[parameters.Length - 1].GetCustomAttributes(typeof(ParamArrayAttribute), false).Length > 0; if (hasParams) { int lastParamPosition = parameters.Length - 1; object[] realParams = new object[parameters.Length]; for (int i = 0; i < lastParamPosition; i++) realParams[i] = input[i]; Type paramsType = parameters[lastParamPosition].ParameterType.GetElementType(); Array extra = Array.CreateInstance(paramsType, input.Length - lastParamPosition); for (int i = 0; i < extra.Length; i++) extra.SetValue(input[i + lastParamPosition], i); realParams[lastParamPosition] = extra; input = realParams; } return Method.Invoke(Target, input); }
请注意,我以非常有限的方式测试了此方法,因此可能仍然存在错误。
假设我们有以下示例类:
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
的签名AddParmsInt
是(int[])
,虽然编译器,作为一种礼貌, 允许你在引擎盖下调用这样的方法(int, int)
真正发生的事情就是调用你的转换。将站点调用到等效(int[])
调用。 通过reflection,您没有编译器的“帮助”,因此您需要传递方法签名定义的确切参数类型。
尽管如此,您的call
方法应如下所示:
public object call(params object[] input) { return AddParamsInts.Invoke(null /*static*/, new object[] { input.Cast().ToArray() }); }
请注意,您不能直接将object[]
数组转换为int[]
数组: int[] ints = (int[])input
。 不允许将引用类型数组转换为值类型数组。
另外需要注意的是, Add
方法的已定义重载是无用的,因为它们重叠。 考虑仅使用params
重载,或者,如果您想要保证至少需要两个参数来评估添加 ,请按以下方式重载它们:
public int Add(int i1, int i2) { } public int Add(int i1, int i2, params int[] args) { }
你应该将参数包装在一个数组中,但编译器会混淆,所以你需要帮助它:
例如:
AddMethod.call((object) new int[] {5, 4 });