是否可以在C#中调用动态对象?

时间:2012-04-17 17:54:26

标签: c# dynamic

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

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“apply”功能。有没有更简单的方法来完成我想要做的事情?我觉得我错过了一些明显的东西。

2 个答案:

答案 0 :(得分:1)

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

根据您的使用情况,您的交换机案例可能实际上是可行的,因为它应该既简单又快速。

使用你的switch case,N是你支持的最大数量的参数,C#编译器将创建N + 1个callite,它只是静态地知道它们在哪里。 Impromptu将调用dlr apis,就像编译器一样,但它将storing the callsite in a hashtable,这将增加查找时间(虽然不错)。

dlr api还要求一个委托有一个与你正在调用的数字或参数相匹配的签名,编译器将确保你静态地拥有N + 1个委托,而Impromptu将使用17个内置的Func<> ;在交换机案例中然后start emiting new delegates as needed,生成一次性成本很高,然后为后续调用添加更多哈希表查找。

答案 1 :(得分:0)

编辑:这不是一个答案 - 保持在这里让其他人知道@Mark不太可能寻找。

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

 MethodInfo magicMethod = magicType.GetMethod("ItsMagic");
 object magicValue = magicMethod.Invoke(magicClassObject, new object[]{100});