如何使用未知参数数组调用C# DynamicObject的TryInvoke方法?
用参数数组调用DynamicObject的可行方案
方法一:借助DLR内置的InvokeBinder(推荐)
不需要自行实现InvokeBinder,.NET通过Microsoft.CSharp.RuntimeBinder.Binder类提供了现成的创建逻辑。只需引用Microsoft.CSharp程序集(.NET Core/.NET 5+需安装同名NuGet包),就能快速构造可用的InvokeBinder实例,直接调用TryInvoke方法。
示例代码:
using System.Dynamic; using Microsoft.CSharp.RuntimeBinder; // 自定义DynamicObject示例 public class MyDynamicObj : DynamicObject { public override bool TryInvoke(InvokeBinder binder, object?[]? args, out object? result) { result = $"执行调用,参数列表:{string.Join(", ", args ?? Array.Empty<object>())}"; return true; } } // 调用逻辑 var dynObj = new MyDynamicObj(); object[] paramArray = new object[] { "参数1", 123, false }; // 创建InvokeBinder实例 var invokeBinder = Binder.Invoke( CSharpBinderFlags.None, null, typeof(Program), // 替换为你的当前类类型 new[] { CSharpArgumentInfo.Create(CSharpArgumentInfoFlags.None, null) } ); // 执行调用 if (dynObj.TryInvoke(invokeBinder, paramArray, out var invokeResult)) { Console.WriteLine(invokeResult); }
方法二:动态调用结合参数展开(适合参数数量有限的场景)
如果不想直接操作TryInvoke,可以封装一个辅助方法,利用dynamic特性结合params实现参数数组的展开调用:
public static dynamic InvokeDynamicTarget(dynamic target, params object[] args) { return args switch { [] => target(), [var a] => target(a), [var a, var b] => target(a, b), [var a, var b, var c] => target(a, b, c), [var a, var b, var c, var d] => target(a, b, c, d), // 可根据业务需求扩展更多参数分支 _ => throw new ArgumentException("未处理的参数数量") }; } // 使用示例 var dynObj = new MyDynamicObj(); object[] paramArray = new object[] { "参数1", 123, false }; var result = InvokeDynamicTarget(dynObj, paramArray); Console.WriteLine(result);
这种方法的局限性是参数数量较多时需要编写大量分支,适合参数个数固定且较少的场景。
方法三:自行实现InvokeBinder(不推荐)
虽然可以自定义InvokeBinder,但DLR的绑定逻辑复杂,自行实现容易引发异常,仅适合测试场景:
public class CustomInvokeBinder : InvokeBinder { public CustomInvokeBinder(CallInfo callInfo) : base(callInfo) { } public override DynamicMetaObject FallbackInvoke(DynamicMetaObject target, DynamicMetaObject[] args, DynamicMetaObject errorSuggestion) { // 简单实现抛出异常,实际场景需完善绑定逻辑 return errorSuggestion ?? new DynamicMetaObject( Expression.Throw(Expression.Constant(new NotImplementedException()), typeof(object)), BindingRestrictions.Empty ); } } // 使用示例 var dynObj = new MyDynamicObj(); object[] paramArray = new object[] { "参数1", 123, false }; var callInfo = new CallInfo(paramArray.Length); var customBinder = new CustomInvokeBinder(callInfo); dynObj.TryInvoke(customBinder, paramArray, out var result); Console.WriteLine(result);
内容的提问来源于stack exchange,提问作者user10619713
相关产品推荐
相关产品推荐

