1

我有一种情况,我有一个可调用的“动态”类型的对象。我正在尝试实现一个函数,该函数将在运行时使用一组参数动态调用对象。如果我在编译时知道参数的数量,就很容易调用它:

Object StaticInvoke(dynamic func, Object[] args) {
    // arguments are explicitly unwrapped and bound to the invokation
    // requiring that we know the number at compile time
    return func(args[0], args[1], ...); 
}

但是,这并不能实现我想要的,因为 args 数组可能是可变长度的。我想不出一种方法来支持任意数量的参数。我想出的最接近的是:

static Object Invoke(dynamic func, Object[] args)
{

    // not sure what to put here
    switch(args.Length)
    {
        case 0:
            return func();
        case 1:
            return func(args[0]);
        case 2:
            return func(args[0], args[1]);
        ...
        default:
            throw new NotSupportedException();
    }
}

这将限制我可能通过的参数数量。我想我可以忍受这个限制,但感觉我正在尝试做的事情应该是可能的。

我基本上是在尝试在 C# 中实现 javascript“应用”函数。有没有更简单的方法来完成我想要做的事情?我觉得我错过了一些明显的东西。

4

2 回答 2

1

开源 apache 许可的 ImpromptuInterface(在 nuget 上)具有执行此操作的静态方法Impromptu.Invoke。您可以查看实现,虽然它处理任意数量的参数,但它也可以工作,您可能不需要,例如提供一种机制来动态描述命名参数并调用它们。

根据您的使用情况,您的 switch case 想法实际上可能是可行的方法,因为它应该既简单又快速。

对于您的 switch 案例,N 是您支持的最大参数数量,C# 编译器将创建 N+1 个调用点,它只是静态地知道它们在哪里。即兴将调用 dlr api,就像编译器一样,但它将调用站点存储在哈希表中,这将增加查找时间(虽然不错)。

dlr api 还需要一个委托,该委托具有与您正在调用的数字或参数相匹配的签名,编译器将再次确保您静态拥有 N+1 个委托,而 Impromptu 将在开关中使用 17 个内置 Func<>情况下,然后根据需要开始发出新的委托,这是一次繁重的生成成本,然后为后续调用添加更多的哈希表查找。

于 2012-04-18T15:32:24.967 回答
0

编辑:这不是一个答案——把它放在这里是为了让其他人知道@Mark 寻找的东西不太可能。

对于常规对象,您将使用MethodBase.InvokeMethod

 MethodInfo magicMethod = magicType.GetMethod("ItsMagic");
 object magicValue = magicMethod.Invoke(magicClassObject, new object[]{100});
于 2012-04-17T17:58:26.457 回答