C#(不是ASP/MVC/WinForms) - 捕获类中的所有异常

jon*_*erg 20 .net c# exception-handling exception

一些背景信息

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

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

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

这个问题

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

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

编辑

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

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

Jonathan Keljo,CLR Exceptions PM

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

哦,我在父系统中得到的错误是Exception has been thrown by the target of an invocation.,据我所知,来自外部.Net异常的消息发生了.如果可以读出任何东西,我不知道.

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

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

我通过使用Castle DynamicProxy设置实现了它.这真的很容易设置.我的测试用例是封装XmlAttribute类的façade类.我要做的第一件事就是编写代理类:

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

然后我必须指示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());
    }
}
Run Code Online (Sandbox Code Playgroud)

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

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

VMA*_*Atm 11

当我理解答案时,你需要抓住并重新抛出未处理的异常,对吧?您可以为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.
  }
Run Code Online (Sandbox Code Playgroud)

更新:

我在AppDomain课堂上发现了另一个事件,AppDomain.FirstChanceException事件:

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

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


jle*_*lew 4

我会考虑使用诸如Castle Dynamic Proxy之类的东西。
这将允许以通用方式拦截您的类方法调用,这将为您提供一个放置“包罗万象”异常处理程序的中心位置。(也就是说,我不清楚你的类是如何实际实例化的,这可能会使这种方法出现问题)