使用可变数量参数的动态调用中的受控异常处理

2024-04-01

In a 昨天的话题已解决 https://stackoverflow.com/questions/9726032/puzzle-involving-unwound-stacks-on-dynamic-invoke/9750323,@hvd 向我展示了如何在处理未知类型的委托时通过 .Invoke 来“控制”异常处理(在像这样的库中出现的问题)Isis2 http://isis2.codeplex.com,其中最终用户提供多态事件处理程序和库类型匹配来决定调用哪个)。 Hvd 的建议围绕着了解上行处理程序接收到多少个参数,然后使用该信息来构造正确类型的泛型,这使他能够构造动态对象并调用它。该序列产生了对异常处理的完全控制。

他建议的核心是 Isis2 可以考虑以这种方式进行上行调用:

MethodInfo mi = typeof(Program).GetMethod("Foo", BindingFlags.Static | BindingFlags.NonPublic); 
Delegate del = Delegate.CreateDelegate(typeof(Action<,>).MakeGenericType(mi.GetParameters().Select(p => p.ParameterType).ToArray()), mi);
((dynamic)del).Invoke(arg0, arg1);

这是我的问题:任何人都可以建议一种方法来做同样的事情,适用于任意数量的参数吗?显然我可以做一个 switch 语句并为 1 arg、2 等的情况编写代码。但是有没有办法在 mi.GetParameters().Length 告诉我们有多少个参数的情况下做到这一点?

对于那些不想单击链接的人来说,核心问题是这样的:在进行此类动态向上调用时,最终用户(注册了被调用的方法)可能会因错误而抛出异常。事实证明,当不在 Visual Studio 下运行时(当直接在 CLR 中运行时),C# .Invoke 将捕获并重新抛出异常,将它们作为内部异常打包在 InitationTargetException 中。这会展开堆栈并导致用户将错误视为调用 .Invoke 的代码(例如,我的代码)存在某种问题。这就是为什么 C# 参考手册认为 catch/rethrow 是一种糟糕的编码实践:应该只捕获计划处理的异常......

hvd 解释说,这基本上是因为 .Invoke 不知道参数的数量或类型,并且在该模式下,显然会出于某种原因捕获并重新抛出异常。他的解决方法本质上是确定参数的数量(示例中的通用参数:Action),这显然足以使 .Invoke 不会执行“通用捕获”。但要将他的示例用于任意代码,我需要为每个可能的参数数量提供一个案例。可行(毕竟,谁会想要超过 16 个?),但丑陋!

因此,今天的挑战是:改进该代码,以便使用类似的 3 行 C# 代码片段,无论有多少参数都可以正常工作。当然,生成的委托也需要可调用,大概是一个对象向量,每个参数一个......

PS:悲观的原因之一:行动本身有 16 种形式,有 1 到 16 个论点。所以对我来说,这表明 C# 开发人员没有看到更通用的方法,最终使用 switch 语句得到了与我相对应的版本(我猜 switch 会有 0 到 16 个参数的情况) ,因为我需要一个带有 N 类型参数的 Action<...> 来处理 N 个用户提供的参数!)


我不想让它永远开放,所以我已经尽我所能来理解核心问题,包括下载 Mono 中 .Invoke 的代码。据我所知,最初的问题只是由于一种优化,当对带有参数向量的对象执行动态 Invoke 时,这种优化有利于更快的调用,但以这种方式捕获异常为代价。使用通用模板创建的动态委托的代码根本没有这个陷阱。

这不是一个很好的答案,但如果无法访问 Invoke 的 .NET 实现,显然不可能给出更好的答案。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

使用可变数量参数的动态调用中的受控异常处理 的相关文章

  • Mono 无法保存用户设置

    我在 Mono Ubuntu 上保存用户设置时遇到问题 这是代码示例 private void Form1 Load object sender EventArgs e string savedText Properties Setting
  • MEX 文件中的断言导致 Matlab 崩溃

    我正在使用mxAssert 宏定义为matrix h在我的 C 代码中 mex 可以完美编译 当我调用的 mex 代码中违反断言时 该断言不会导致我的程序崩溃 而是导致 Matlab 本身崩溃 我错过了什么吗 这是有意的行为吗 当我查看 M
  • 为什么基类必须有一个带有 0 个参数的构造函数?

    这不会编译 namespace Constructor0Args class Base public Base int x class Derived Base class Program static void Main string a
  • ZLIB 解压缩

    我编写了一个小型应用程序 该应用程序应该解压缩以 gzip deflate 格式编码的数据 为了实现这一点 我使用 ZLIB 库 使用解压缩功能 问题是这个功能不起作用 换句话说 数据不是未压缩的 我在这里发布代码 int decompre
  • 为什么 BOOST_FOREACH 不完全等同于手工编码的?

    From 增强文档 http www boost org doc libs 1 48 0 doc html foreach html foreach introduction what is literal boost foreach li
  • VS30063:您无权访问 https://dev.azure.com

    我正在尝试在 asp net core 2 1 mvc 应用程序中使用以下代码连接 Azure DevOps Uri orgUrl new Uri https dev azure com xxxxx String personalAcces
  • 在 C# 中将位从 ulong 复制到 long

    所以看来 NET 性能计数器类型 http msdn microsoft com en us library system diagnostics performancecounter aspx有一个恼人的问题 它暴露了long对于计数器
  • 转到 C# WPF 中的第一页

    我正在 WPF 中使用导航服务 为了导航到页面 我使用 this NavigationService Navigate new MyPage 为了返回我使用 this NavigationService GoBack 但是如何在不使用的情况
  • 禁用 LINQ 上下文的所有延迟加载或强制预先加载

    我有一个文档生成器 目前包含约 200 个项目的查询 但完成后可能会超过 500 个 我最近注意到一些映射表示延迟加载 这给文档生成器带来了一个问题 因为它需要根据生成的文档来访问所有这些属性 虽然我知道DataLoadOptions可以指
  • 为什么 FTPWebRequest 或 WebRequest 通常不接受 /../ 路径?

    我正在尝试从 ftp Web 服务器自动执行一些上传 下载任务 当我通过客户端甚至通过 Firefox 连接到服务器时 为了访问我的目录 我必须指定如下路径 ftp ftpserver com AB00000 incoming files
  • 范围和临时初始化列表

    我试图将我认为是纯右值的内容传递到范围适配器闭包对象中 除非我将名称绑定到初始值设定项列表并使其成为左值 否则它不会编译 这里发生了什么 include
  • C# 创建数组的数组

    我正在尝试创建一个将使用重复数据的数组数组 如下所示 int list1 new int 4 1 2 3 4 int list2 new int 4 5 6 7 8 int list3 new int 4 1 3 2 1 int list4
  • 用于从字符串安全转换的辅助函数

    回到 VB6 我编写了一些函数 让我在编码时无需关心字符串的 null 和 数字的 null 和 0 等之间的区别 编码时 没有什么比添加特殊情况更能降低我的工作效率了用于处理可能导致一些不相关错误的数据的代码 9999 10000 如果我
  • 过期时自动重新填充缓存

    我当前缓存方法调用的结果 缓存代码遵循标准模式 如果存在 则使用缓存中的项目 否则计算结果 在返回之前将其缓存以供将来调用 我想保护客户端代码免受缓存未命中的影响 例如 当项目过期时 我正在考虑生成一个线程来等待缓存对象的生命周期 然后运行
  • 运行代码首先迁移更新数据库时出错

    我在迁移到数据库时遇到问题 并且似乎找不到我遇到的错误的答案 System MissingMethodException Method not found System Data Entity Migrations Builders Tab
  • 同时从多个流中捕获、最佳方法以及如何减少 CPU 使用率

    我目前正在编写一个应用程序 该应用程序将捕获大量 RTSP 流 在我的例子中为 12 个 并将其显示在 QT 小部件上 当我超过大约 6 7 个流时 问题就会出现 CPU 使用率激增并且出现明显的卡顿 我认为它不是 QT 绘制函数的原因是因
  • 如何在 GCC 5 中处理双 ABI?

    我尝试了解如何克服 GCC 5 中引入的双重 ABI 的问题 但是 我没能做到 这是一个重现错误的非常简单的示例 我使用的GCC版本是5 2 如您所见 我的主要函数 在 main cpp 文件中 非常简单 main cpp include
  • 如何查明CONFIG_FANOTIFY_ACCESS_PERMISSIONS是否启用?

    我想利用fanotify 7 http man7 org linux man pages man7 fanotify 7 html我遇到的问题是在某些内核上CONFIG FANOTIFY ACCESS PERMISSIONS不起作用 虽然C
  • 如何确定母版页中正在显示哪个子页?

    我正在母版页上编写代码 我需要知道正在显示哪个子 内容 页面 我怎样才能以编程方式做到这一点 我用这个 string pageName this ContentPlaceHolder1 Page GetType FullName 它以 AS
  • 如何创建向后兼容 Windows 7 的缩放和尺寸更改每显示器 DPI 感知应用程序?

    我是 WPF 和 DPI 感知 API 的新手 正在编写一个在 Windows 7 8 1 和 10 中运行的应用程序 我使用具有不同每个显示器 DPI 设置的多个显示器 并且有兴趣将我的应用程序制作为跨桌面配置尽可能兼容 我已经知道可以将

随机推荐