统一处理许多例外情况

时间:2011-12-14 13:35:26

标签: c# .net exception exception-handling

在我目前的项目中,我正在与一些第三方中间件进行交互,这些中间件会抛出许多不同类型的异常(大约10个或更多异常)。

我使用第三方的图书馆有一些方法,每个方法都与第三方交互,但需要保护它们不受同一组10个或更多例外的影响。

我目前所拥有的是我的图书馆的每一种方法:

try
{
   // some code
}
catch (Exception1 e)
{
}
catch (Exception2 e2)
{
}
  ...
catch (ExceptionN eN)
{
}

异常的数量也可能会增加。

如何减少代码重复并在一个地方统一处理所有异常?

  • 假设我的代码中每个方法的处理是相同的。

5 个答案:

答案 0 :(得分:5)

我首先要捕获基础Exception类型,然后使用白名单进行过滤:

try
{
   // Code that might throw.
}
catch (Exception e)
{
    if(e is Exception1 || e is Exception2 || e is ExceptionN) 
    {
         // Common handling code here.
    }
    else throw; // Can't handle, rethrow.
}

现在,如果您想要概括过滤器,可以编写扩展名:

public static bool IsMyCustomException(this Exception e)
{
    return e is Exception1 || e is Exception2 || e is ExceptionN;
}

然后你可以使用:

if(e.IsMyCustomException())
{
    // Common handling code here.
}
else throw;

您可以使用一种简单的方法来概括处理程序

private void HandleCustomException(Exception e)
{
    // Common handling code here.
}

如果你想要概括整个try-catch块,你可能最好将一个委托注入一个包装操作的方法,如@vc 74所述。

答案 1 :(得分:3)

您可以使用全局异常处理程序,实现取决于您的项目类型(ASP.net - > global.asax,WPF - > App.xaml ...)

或使用以下内容:

private static void HandleExceptions(Action action)
{
    try
    {
       action();
    }
    catch (Exception1 e)
    {
    }
    catch (Exception2 e2)
    {
    }
      ...
    catch (ExceptionN eN)
    {
    }
}

可以通过以下方式调用:

HandleExceptions(() => Console.WriteLine("Hi there!"));

如果在执行Console.WriteLine期间抛出了异常,那么它将由您的异常处理逻辑处理

请注意,要执行的代码也可能会修改外部值:

int x = 2;
HandleExceptions(() => x = 2 * x);

如果您更喜欢匿名方法:

var x = 2;
HandleExceptions(delegate()
{
  x = x * 2;
});

答案 2 :(得分:1)

如何使用一个函数来处理这些异常:

try
{
  //Some code here
}
catch(Exception e)
{
  if(!ErrorHandler(e))
      return null; //unhandled situation
}

private bool ErrorHandler(Exception e)
{
 switch(e)
 {
     case Exception1:
     //Handle the exception type here
     return true;
     case Exception2:
     //Handle another exception type here
     return true;
 }
 return false;
}

答案 3 :(得分:1)

我建议使用Enterprise Library 5.0异常处理块。基本上,您定义了多个异常类型,类别和处理特定异常类型的异常处理程序。理想情况下,您将定义异常类型,将其连接到格式化程序,然后使用Logging块报告异常。

You can read all about it here...

答案 4 :(得分:-1)

捕获和重新抛出异常与捕获异常之间存在一些语义差异。因此,例外过滤器非常有用,因为它们允许例如过滤器。 “在IsNiceException(Ex)时捕获Ex Exception”。不幸的是,在C#程序中使用它们的唯一方法是使用DLL来包装必要的功能(DLL本身可以用vb或其他语言编写)。典型的模式可能是:

  TryWhenCatchFinally( 
    () => {trycode;},
    (Exception ex) => {codeWhichReturnsTrueForExceptionsWorthCatching;},
    (Exception ex) => {codeToHandleException;},
    (ExceptionStatus status, Exception ex) => {finallyCode;});

“finally”代码的ExceptionStatus参数将是一个枚举,说明是否(1)没有发生异常,(2)发生了异常,但是被处理,(3)发生异常并被处理,但是另一个例外是抛出,或(4)发生异常但CodeWhichReturnsTrueForExceptionsWorthCatching返回false; (5)发生了一个异常,它没有在trycode中处理,也没有被这个块处理,但是无论如何都完成了trycode(一种罕见的情况,但它有可能发生的方式)。在第一种情况下,Ex参数将为null,并且在其他情况下包含适当的异常 - 如果在处理finally块时发生异常则可能有用的信息(抑制在finally块中发生的异常可能是坏的,但是如果在新异常转义之前,未记录或丢失早期异常,来自先前异常的所有数据通常都将丢失;如果导致先前异常的相同条件导致后一异常,则先前的异常可能包含有关内容的更多有用信息错)。

BTW,这个模式的一些注释:

  1. 决定是否捕获异常的代码将在嵌套的finally块执行之前运行;它可以捕获有用的数据用于日志记录(最终块没有运行的事实可能可用于记录将被嵌套的finally块破坏的信息),但实际清理通常应该在finally块运行之后完成。
  2. 目前,似乎从过滤器中逃脱的异常会被扼杀,但我不确定这种行为是否得到保证。可能无法在过滤器内完成可能泄漏异常的操作。
  3. 如果“trycode”包含嵌套在try-catch块中的try-finally块,则TryCatchWhenFamily不会处理在try-finally块的“try”部分中发生的异常。任何嵌套的作用域,但是由外部块处理,并且内部try-finally块的处理抛出内部try-catch块处理的异常,外部块已经确定它将捕获的异常可能会消失而没有永远被抓住了。如果TryWhenCatchFinally方法被编码以检测这种情况,它可以让它的finally块代码知道(finally块可能或可能不想对该条件做任何事情,但它应该至少应该被记录)。