是否可以在 C# 中调用动态对象
本文关键字:调用 动态 对象 是否 | 更新日期: 2023-09-27 18:31:29
我有一个可调用的"动态"类型的对象。我正在尝试实现一个函数,该函数将使用一组参数在运行时动态调用对象。如果我知道编译时的参数数量,调用它很容易:
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" 函数。有没有更简单的方法来完成我想要做的事情?我觉得我错过了一些明显的东西。
开源 apache 许可的 ImpromptuInterface(在 nuget 上)有一个静态方法 Impromptu.Invoke 来做到这一点。您可以查看实现,虽然它处理任意数量的参数,但它也确实可以正常工作,例如提供动态描述命名参数并调用它们的机制。
根据您的使用情况,您的开关案例想法实际上可能是要走的路,因为它应该既简单又快速。
对于开关大小写,N 是您支持的最大参数数,C# 编译器将创建 N+1 个调用站点,它只是静态地知道它们的位置。即兴将调用 dlr API,就像编译器一样,但它会将调用站点存储在哈希表中,这将增加查找时间(虽然还不错)。
dlr api 还需要一个委托,该委托的签名与您调用的数字或参数相匹配,编译器将再次确保您静态拥有 N+1 个委托,而 Impromptu 将使用 17 个内置 Func<> 在开关情况下,然后根据需要开始发出新委托,生成是一次性的沉重成本,然后为后续调用添加更多哈希表查找。
编辑:这不是一个答案 - 把它留在这里让其他人知道它不太可能是@Mark寻找的。
对于常规对象,您将使用MethodBase.InvokeMethod
:
MethodInfo magicMethod = magicType.GetMethod("ItsMagic");
object magicValue = magicMethod.Invoke(magicClassObject, new object[]{100});