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

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(使用前将#替换为@)

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

  • 在模板类中声明模板友元类时出现编译器错误

    我一直在尝试实现我自己的链表类以用于教学目的 我在迭代器声明中指定了 List 类作为友元 但它似乎无法编译 这些是我使用过的 3 个类的接口 Node h define null Node
  • 类型中的属性名称必须是唯一的

    我正在使用 Entity Framework 5 并且有以下实体 public class User public Int32 Id get set public String Username get set public virtual
  • 如何在 Cassandra 中存储无符号整数?

    我通过 Datastax 驱动程序在 Cassandra 中存储一些数据 并且需要存储无符号 16 位和 32 位整数 对于无符号 16 位整数 我可以轻松地将它们存储为有符号 32 位整数 并根据需要进行转换 然而 对于无符号 64 位整
  • C++11 删除重写方法

    Preface 这是一个关于最佳实践的问题 涉及 C 11 中引入的删除运算符的新含义 当应用于覆盖继承父类的虚拟方法的子类时 背景 根据标准 引用的第一个用例是明确禁止调用某些类型的函数 否则转换将是隐式的 例如最新版本第 8 4 3 节
  • 如何从 Visual Studio 将视图导航到其控制器?

    问题是解决方案资源管理器上有 29 个项目 而且项目同时具有 ASP NET MVC 和 ASP NET Web 表单结构 在MVC部分中 Controller文件夹中有大约100个子文件夹 每个文件夹至少有3 4个控制器 视图完全位于不同
  • std::vector 与 std::stack

    有什么区别std vector and std stack 显然 向量可以删除集合中的项目 尽管比列表慢得多 而堆栈被构建为仅后进先出的集合 然而 堆栈对于最终物品操作是否更快 它是链表还是动态重新分配的数组 我找不到关于堆栈的太多信息 但
  • 如何连接重叠的圆圈?

    我想在视觉上连接两个重叠的圆圈 以便 becomes 我已经有部分圆的方法 但现在我需要知道每个圆的重叠角度有多大 但我不知道该怎么做 有人有主意吗 Phi ArcTan Sqrt 4 R 2 d 2 d HTH Edit 对于两个不同的半
  • 重载 (c)begin/(c)end

    我试图超载 c begin c end类的函数 以便能够调用 C 11 基于范围的 for 循环 它在大多数情况下都有效 但我无法理解和解决其中一个问题 for auto const point fProjectData gt getPoi
  • 方程“a + bx = c + dy”的积分解

    在等式中a bx c dy 所有变量都是整数 a b c and d是已知的 我如何找到整体解决方案x and y 如果我的想法是正确的 将会有无限多个解 由最小公倍数分隔b and d 但我只需要一个解决方案 我可以计算其余的 这是一个例
  • 使用 C# 中的 CsvHelper 将不同文化的 csv 解析为十进制

    C 中 CsvHelper 解析小数的问题 我创建了一个从 byte 而不是文件获取 csv 文件的类 并且它工作正常 public static List
  • 两个静态变量同名(两个不同的文件),并在任何其他文件中 extern 其中一个

    在一个文件中将变量声明为 static 并在另一个文件中进行 extern 声明 我认为这会在链接时出现错误 因为 extern 变量不会在任何对象中看到 因为在其他文件中声明的变量带有限定符 static 但不知何故 链接器 瑞萨 没有显
  • 结构体的内存大小不同?

    为什么第一种情况不是12 测试环境 最新版本的 gcc 和 clang 64 位 Linux struct desc int parts int nr sizeof desc Output 16 struct desc int parts
  • 如何定义一个可结构化绑定的对象的概念?

    我想定义一个concept可以检测类型是否T can be 结构化绑定 or not template
  • 为什么 isnormal() 说一个值是正常的,而实际上不是?

    include
  • 为什么C++代码执行速度比java慢?

    我最近用 Java 编写了一个计算密集型算法 然后将其翻译为 C 令我惊讶的是 C 的执行速度要慢得多 我现在已经编写了一个更短的 Java 测试程序和一个相应的 C 程序 见下文 我的原始代码具有大量数组访问功能 测试代码也是如此 C 的
  • C++ 中的参考文献

    我偶尔会在 StackOverflow 上看到代码 询问一些涉及函数的重载歧义 例如 void foo int param 我的问题是 为什么会出现这种情况 或者更确切地说 你什么时候会有 对参考的参考 这与普通的旧参考有何不同 我从未在现
  • 在OpenGL中,我可以在坐标(5, 5)处精确地绘制一个像素吗?

    我所说的 5 5 正是指第五行第五列 我发现使用屏幕坐标来绘制东西非常困难 OpenGL 中的所有坐标都是相对的 通常范围从 1 0 到 1 0 为什么阻止程序员使用屏幕坐标 窗口坐标如此严重 最简单的方法可能是通过以下方式设置投影以匹配渲
  • MySQL Connector C/C API - 使用特殊字符进行查询

    我是一个 C 程序 我有一个接受域名参数的函数 void db domains query char name 使用 mysql query 我测试数据库中是否存在域名 如果不是这种情况 我插入新域名 char query 400 spri
  • 指针和内存范围

    我已经用 C 语言编程有一段时间了 但对 C 语言还是很陌生 有时我对 C 处理内存的方式感到困惑 考虑以下有效的 C 代码片段 const char string void where is this pointer variable l
  • 从 mvc 控制器使用 Web api 控制器操作

    我有两个控制器 一个mvc控制器和一个api控制器 它们都在同一个项目中 HomeController Controller DataController ApiController 如果我想从 HomeController 中使用 Dat

随机推荐