Postsharp 重新捕获异常被自己捕获并重新抛出

Postsharp recatch exception beeing caught and rethrown by itself

我希望能够使用 Postsharp OnMethodBoundary.OnException 捕获异常。但只有一次。让我解释一下。

我有这些方法:

public void FooV1(){
    throw new NotYetImplementedException();
}
public void FooV2(){
    try{    
        throw new NotYetImplementedException();
    } catch(Exception) {
        Console.Writeline("Exception has be caught by catch block.");
    }
}

还有这个 OnException :

public void OnException(MethodExecutionArgs args){
    Console.Writeline("Exception has be caught by Postsharp.");
}

当异常发生时,异常被捕获,我做了一些工作(保存上下文)但我不想干扰程序工作流程。因此,如果在 try catch 块中引发异常,它将被捕获,如果没有,则将引发异常。

如果在OnException(...)我用args.FlowBehavior = FlowBehavior.Default;

我得到: 在 Foov1 中:

Exception has be caught by Postsharp. Exception has be caught by Postsharp.

因为当重新抛出的 Postsharp 中的异常重新捕获时(但只有一次?我希望它循环)。我想让 OnException 只被调用一次,如果异常没有在调用堆栈的更高层被捕获,那么程序应该停止。

在 FooV2 中:

Exception has be caught by Postsharp. Exception has be caught by catch block.

我得到了预期的结果。

我无法使用 FlowBehavior.ContinueFlowBehavior.Return,因为无法到达 catch 块。 我看不出 FlowBehavior.ThrowFlowBehavior.Rethrow

之间的区别

我该如何解决?

我不知道您的实际代码是什么,但您可能将 OnException 方面应用于两个或多个方法:抛出原始异常的方法和捕获异常的方法。这可以解释为什么您两次看到 OnException 消息。

当你这样做时

[YourPostSharpOnExceptionAspect]
void A() 
{
 // code 
}

它被翻译成大致如下:

void A() 
{
  try { 
   // code
  } catch (Exception e) {
   yourPostSharpOnExceptionAspectInstance.OnException(e);
   throw;
  }
}

由于每个 PostSharp 方面不断重新抛出相同的异常,您将多次捕获它。

您可能需要添加自己的代码来仅处理一次异常。你可以这样做:

public void OnException(MethodExecutionArgs args){
    if (args.Exception.Data["Handled"]) {
      // do nothing, already saved
      args.FlowBehavior = FlowBehavior.Rethrow;
    }
    else 
    {
      // first time seeing this exception, do stuff....
      args.Exception.Data["Handled"] = true; // and mark the exception as processed
      args.FlowBehavior = FlowBehavior.Throw;  
    }
}

ThrowRethrow 之间的区别在于 Throw 在代码中添加了类似 throw args.Exception 的内容,而 Rethrow 仅添加了 throw;重新抛出最初捕获的异常(并保留原始堆栈跟踪)。