C#(不是ASP / MVC / WinForms) – 捕获类中的所有exception

一些背景信息

我在一个使用专有编程语言的系统中编程,可以选择在专有代码中使用特别归属的.Net类。

不幸的是,系统没有处理从.Net代码冒出来的未处理exception,如果事实上根本没有; 系统崩溃,没有任何解释。 这很烦人,因为我们经常想要处理专有系统中的exception,而不是.Net代码。 系统供应商提供的解决方案是将exception重新打包到系统确实处理的特殊对象中。

我们的.Net代码是以façade模式编写的,问题是为了确保处理来自.Net代码的每个exception,Facade中的每个方法都必须包含一个try / catch块,它可以重新打包任何可能的exception。发生。

这个问题

我在这里阅读了很多描述类似场景的线程,其中大多数是WinForms-或与web相关。 因为我们的代码都不是,所以问题是是否有某种方法来捕获类中的所有exception,以便我们可以重新打包它并重新抛出它们的修改版本?

显然,包含类和。专有语言的.Net dll之间的接口完全超出了我们的控制范围。

编辑

我尝试了@VMAtm建议的currentDomain.UnhandledException方法,遗憾的是无济于事。 事件处理程序没有触发,父系统得到exception,然后像往常一样行为不端。 这让我再次进入谷歌,我在这里找到了这一段:

首先要理解的是UnhandledException事件不是未处理的exception“处理程序”。 注册事件,与文档说的相反:-(,不会导致未处理的exception被处理。(从那以后它们将不会被处理,但我将停止循环推理已经……)UnhandledException事件只是通知您exception未处理,以防您想要在线程或应用程序死亡之前尝试保存状态。

Jonathan Keljo,CLR Exceptions PM

这太糟糕了,我喜欢有一个“全局”try / catch块的想法。 我猜这意味着我没有成功地从父系统中隐藏exception。 因为我不知道关于如何在该系统中实现它的第一件事(坦率地说,我不知道我将如何继续自己实现它的第一件事)我和我一起真的很薄假设,所以如果有人能以任何方式纠正我,请继续!

哦,我在父系统中得到的错误是Exception has been thrown by the target of an invocation. ,据我所知,来自外部.Netexception的消息发生了。 如果可以阅读其中的任何内容,我不知道。

我也会去@jlew建议的Castle Dynamic Proxy,但它看起来比两条AppDomain线要困难得多,让我害怕得多:)

如果你遇到与我相同的问题,你应该首先尝试@VMAtm建议的currentDomain.UnhandledException方法,因为这是因为我的父系统特别肛门它不起作用。

我使用Castle DynamicProxy设置让它工作。 这真的很容易设置。 我的测试用例是封装XmlAttribute类的façade类。 我要做的第一件事就是编写代理类:

 public class AttribInterceptor : IInterceptor { public void Intercept(IInvocation invocation) { try { invocation.Proceed(); } catch (Exception e) { // Custom exception repackaging here } } } 

然后我必须指示façade对象实际使用代理。 我保留了我的旧后端字段,但在c’tor中添加了以下内容:

 public class CapXmlAttribute : CapPmlNetObject { private XmlAttributeBackend _xmlAttribute; public CapXmlAttribute() { var generator = new ProxyGenerator(); _xmlAttribute = (XmlAttributeBackend) generator.CreateClassProxy( typeof (XmlAttributeBackend), new AttribInterceptor()); } } 

最后一步是将后端中暴露给façade的所有方法设置为virtual 。 对我来说这不是问题,但对其他人来说可能是一个破坏者。

DynamicProxy确实没有那么好记录,但我从KrzysztofKoźmic的教程和Hamilton Verissimo的代码项目中学到了很多东西 。

我会看一下像Castle Dynamic Proxy这样的东西。
这将允许以通用方式拦截您的类方法调用,这将为您提供放置“catch-all”exception处理程序的中心位置。 (也就是说,我不清楚你的类实际上是如何实例化的,这可能会使这种方法成为问题)

当我理解答案时,你需要抓住并重新抛出未处理的exception,对吧? 您可以为AppDomain.UnhandledException事件添加处理程序:

  AppDomain currentDomain = AppDomain.CurrentDomain; currentDomain.UnhandledException += new UnhandledExceptionEventHandler(MyHandler); static void MyHandler(object sender, UnhandledExceptionEventArgs args) { Exception e = (Exception) args.ExceptionObject; // handle exception here, you can easily package exceptions there. } 

更新:

我在AppDomain类中发现了另一个事件AppDomain.FirstChanceException事件 :

在运行时在应用程序域中搜索调用堆栈中的exception处理程序之前,在托管代码中抛出exception时发生。

可能这可以解决您的问题 – 此事件发生在catch块中的任何代码之前

除了VMAtm的post,您还可以为ThreadExceptions设置事件处理程序