是否可以检查是否在更高的应用程序级别处理了异常以跳过日志记录并重新抛出?这样,例如:
try
{
// Execute some code
}
catch (Exception e)
{
if(!ExceptionIsHandled())
LogError(e);
throw e;
}
我不知道。如果您致力于这种设计(请参阅末尾的注释),则可以为某种HandledException
的Exception编写包装,并将其InnerException
设为抛出的异常。然后,您可以使代码看起来像:
try
{
// Execute some code
}
catch (HandledException e)
{
LogError(e.InnerException);
// Do something else
}
catch (Exception e)
{
throw ;
}
答案是刻板的Stackoverflow“您做错了” ...
但是,如果您确实“处理”了异常,则重新抛出异常没有多大意义。也许您的方法应该只返回失败结果,可能包括Exception
作为发生问题的详细信息。
[不,还没到那儿。异常通过处理程序冒出来。通常的方法。是定义您自己的异常,然后仅捕获将要处理的异常。
如果可以确定代码是否包装在专门设计的try-catch块中,该块是用支持异常过滤器的语言编写的,则可以在展开堆栈之前或期间确定是否有可能捕获到异常通过那个外部块或一个内部块。但是,此方法的用途非常有限,特别是考虑到极其常见的代码捕获和重新抛出异常的反模式(它知道它不会解决,仅出于发现它们发生的目的)。
如果您的目标仅仅是避免冗余日志记录,建议您使用可以有效处理冗余的日志记录工具。虽然有些人可能会认为在外部层只记录一次异常会更好,但是拥有更多的记录机会也是有好处的。如果在内层中发生异常而中间层将其吞没,则外层中的日志记录代码将永远不会发现它。相比之下,如果内层通过捕获异常并安排对其进行记录而开始,那么即使中间层吞下了该异常,它发生的事实仍然可以被记录。
这很旧,但是我在这里有一些建议。我之前使用过一种设计模式,可以很好地完成此任务,但确实会增加所有内容的开销。
[基本上,所有方法都将返回响应对象(例如Response<T>
)。任何发生的异常都应该包装在响应对象中,并返回而不是抛出异常。
public class Response<T>
{
public T Payload { get; set; }
public bool IsSuccessful { get; set; } = false;
public string Message { get; set; }
public Exception Error { get; set; }
}
public class MyService
{
public Response<IEnumerable<Customer>> GetCustomers()
{
var response = new Response<IEnumerable<Customer>>();
try
{
var customers = new List<Customer>()
{
new Customer() { CompanyName = "ABC Co." },
new Customer() { CompanyName = "ACME" }
};
response.Payload = customers;
response.IsSuccessful = true;
}
catch (Exception e)
{
response.IsSuccessful = false;
response.Error = e;
// A friendly message, safe to show to users.
response.Message = "An error occurred while attempting to retrieve customers.";
}
return response;
}
}
您可以在不重新抛出异常的情况下冒泡,并进行适当处理。然后,您可以添加异常捕获以获取更多自定义的用户友好消息。
对于安全显示给客户端的任何错误,我也使用自定义基本异常类型。这样,我可以在控制器级别添加通用捕获,以传播那些准备好的错误消息。