如何记录异常并重新抛出为实际类型
如何记录异常并重新抛出为实际类型
我有一个查询处理程序装饰器,它记录任何异常:
public class QueryHandlerLogDecorator: IQueryHandler where TQuery : IQuery { private readonly IQueryHandler _handler; private readonly ILog _log; public QueryHandlerLogDecorator(IQueryHandler handler) { _handler = handler; _log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); } public TResult Handle(TQuery query) { try { var result = _handler.Handle(query); _log.Info("Ok"); return result; } catch (Exception ex) { _log.Error(ex.Message, ex); throw new Exception(ex.Message); } } }
虽然异常处理并不是世界上最糟糕的事情,但它意味着我丢失了被抛出异常的类型。
例如,如果我在应用程序的较低层抛出ApplicationException,它会被捕获并重新抛出为Exception。
如何将捕获的异常重新抛出为原始类型?
问题的原因是在捕获异常后,使用throw关键字重新抛出异常时,无法保留原始异常的类型信息。这可能会导致在处理异常时丢失关键的调试信息。
解决方法是使用throw关键字时,将原始异常作为参数重新抛出。这样可以确保异常的类型信息得以保留,并能够提供准确的异常类型给异常处理程序。
在上述代码示例中,我们可以看到在捕获异常后,使用throw关键字将异常重新抛出。这样做可以确保异常的类型信息不被丢失。通过将原始异常作为参数传递给throw关键字,可以将异常重新抛出为其实际类型。
下面是修改后的代码示例,展示了如何正确地记录异常并重新抛出异常的实际类型:
public TResult Handle(TQuery query) { try { var result = _handler.Handle(query); _log.Info("Ok"); return result; } catch (Exception ex) { _log.Error(ex.Message, ex); throw ex; } }
通过将原始异常作为参数传递给throw关键字,我们可以确保异常的类型信息得以保留,并能够提供准确的异常类型给异常处理程序。这样可以帮助我们更好地定位和解决问题,并提供更好的调试信息。
在处理异常时,有时我们需要将异常记录下来并重新抛出,以便在之后的处理中能够准确地获取异常的信息和调用栈。然而,如果我们使用throw new...
或throw ex;
来重新抛出异常,会导致原始的调用栈信息丢失。
解决这个问题的方法是使用throw;
语句来重新抛出异常,而不指定具体的异常类型。这样做会保留原始的调用栈信息,使得在捕获该异常时能够准确地获取到异常的来源和调用路径。
具体来说,当我们使用throw;
语句重新抛出异常时,异常的调用栈会重新从当前方法开始,并包含原始方法抛出异常的调用路径。这样做的好处是能够避免丢失原始调用栈信息,提供更准确的错误追踪。
如果我们想要了解更多关于该问题的信息,可以参考微软官方文档:MSDN。
总结起来,当我们需要记录异常并重新抛出时,使用throw;
语句而不指定具体的异常类型可以保留原始调用栈信息,提供更准确的错误追踪和处理。这是一种有效的异常处理方法,可以帮助我们更好地调试和修复代码中的问题。