我有一个看起来像的函数:
FuncA(int num, object[] x)
这个函数将使用以这种方式编写的函数:
FuncB(string s, object x1)
FuncB(string s, object x1, object x2)
...
这样,函数B有很多这种形式的重载(实际上是32)并且是一个给定的函数(我无法访问它)。
我想在FuncA中调用FuncB,以便根据输入对象的长度调用正确的重载。
有一种聪明的方法吗?
由于
答案 0 :(得分:3)
如果所有FuncB
方法都属于同一个类,则可以使用Type.GetMethod
重载,该重载接受包含每个参数的确切类型的Type[]
参数。
另一方面,如果每个方法都是从其他地方提供的,您可以将它们存储在数组或字典中(即将“参数数量”映射到每个具体方法):
map[1] = (object[] x) => FuncB(x[0]);
map[2] = (object[] x) => FuncB(x[0], x[1]);
但是,我想知道你的设计是否正确,或许可以更好的方式实施。
答案 1 :(得分:0)
如果您不介意使用反射,那么您应该可以使用这种代码执行此操作:
int FuncA(int num, object[] x)
{
if (x.Length == 0 || x.Length > 32) throw new ArgumentOutOfRangeException();
IEnumerable<Type> types = new[] { typeof(string) }.Concat(x.Select(i => typeof(object)));
MethodInfo info = typeof(FuncBClass).GetMethod("FuncB", types.ToArray());
IEnumerable<object> parameters = new[] { "Some string" }.Concat(x);
object result = info.Invoke(null /* ignored if the method is static */, parameters.ToArray());
return (int)result;
}
基本上就是它的作用:
IEnumerable<Type>
目标方法重载的类型(FuncB有一个字符串,然后是n个对象x1 ... xn)MethodInfo
对象IEnumerable<object>
以传递给该方法重载,因此您的字符串然后是对象列表备注:
FuncBClass
类,其中包含您需要的所有方法null
传递给Invoke
方法,因为我认为这些方法是静态的。如果他们不是,您可能需要调整该行并创建其类的实例以传递给Invoke
方法以使其正常工作 修改:这是一个示例,如果其中一个FuncB
参数是out
参数,则由OP建议。我假设参数是此处x1..xn数列表中的第一个参数,无论如何,对于每个可能的位置,一般的想法是相同的(或者如果out
也是字符串)。< / p>
int FuncA(int num, object[] x)
{
if (x.Length == 0 || x.Length > 32) throw new ArgumentOutOfRangeException();
IEnumerable<Type> types = new[] { typeof(string) }.Concat(x.Select(i => typeof(object)));
MethodInfo info = typeof(int).GetMethod("FuncB", types.ToArray());
object[] parameters = new[] { "Some string", null /* the out parameter */ }.Concat(x.Skip(1)).ToArray();
info.Invoke(null /* ignored if the method is static */, parameters);
return (int)parameters[1]; // Get the out parameter value and cast it
}
答案 2 :(得分:0)
如果这是一个相当孤立的案例,并且你需要它是快速的,我可能会编写子弹并在长度上使用开关而不是使用反射(这将是更简洁的代码,但更慢)
所以
switch(num)
{
case 1: return FuncB(x[0]);
case 2: return FuncB(x[0], x[1]);
etc
虽然丑陋,但速度相当快。
如果这是库中的常见模式,我可能会考虑使用一些代码生成来创建带适配器的程序集。或许某人已经创建了一个包装库。