假设我有一个 Web API 服务,它调用我的用户服务来返回用户个人资料信息等。
UserProfileService
可以抛出 UserNotFoundException
。抛出时,它会被序列化并作为 AggregateException 中的内部异常发送,可以在调用方法中捕获该异常。此服务使用 Service Fabric 的服务远程处理进行 RPC。
我的 WebAPI 正在这样调用我的服务:
[HttpGet]
public async Task<IActionResult> Get(int id)
{
try
{
var profile = await _userService.GetProfileAsync(int id);
return Json(profile);
} catch (AggregateException ae)
{
// Here I want to call NotFound() if `UserNotFoundException`
// was thrown, otherwise...
return StatusCode(StatusCodes.Status500InternalServerError);
}
}
这里有几个问题:
- 我该如何处理预期的异常?
天真地我会做这样的事情:
try { /* ... */ } catch (AggregateException ae)
{
foreach(var e in ae.InnerExceptions)
{
if (e is UserNotFoundException)
{
return NotFound();
}
}
return errorResponse ?? StatusCode(StatusCodes.Status500InternalServerError);
}
但这样做的问题是,如果存在多个异常,则只有一个会“获胜”。而且,我相信 - 尽管不能保证,最早添加的 Exception
将具有优先级,因为它们在 InnerExceptions
中的索引较低。我是否想得太多了,这个解决方案可以吗?唯一一次抛出我的自定义异常是当我知道应该抛出它们时,当然吗?
这引出了我的另一个问题:
- 在什么情况下您会在
AggregateException
中检索多个异常。
当你有任务a
调用任务b
调用任务c
时,c
抛出,b
不抛出,a
抛出,您会得到包含 a
和 c
异常的聚合异常吗?
最佳答案
我会倒着回答你的问题:
2) AggregateException
有一个contructor允许 IEnumerable<Exception>
作为参数。这就是它可以包含多个内部异常的方式。这意味着您的聚合异常不会包含多个内部异常,除非您显式抛出 AggregateException
有多个内部异常。假设您有一个 Task a
调用Task b
调用Task c
。如果c
抛出异常,该异常未在 a
中捕获或b
, a
会抛出 AggregateException
带内AggregateException
c
抛出内部异常.
1)你的例子运行得很好。如果你想要它短一点,你可以通过内部异常捕获它:
try
{
// ...
}
catch (AggregateException ex) when (ex.InnerException is UserNotFoundException)
{
// ...
}
catch (AggregateException ex) when (ex.InnerException is SomeOtherException)
{
// ...
}
您还可以使用一些 if 语句来捕获它们,就像您在示例中所做的那样:
try
{
// ...
}
catch (AggregateException ex)
{
if (ex.InnerException is UserNotFoundException)
{
// ...
}
else if (ex.InnerException is SomeOtherExeption)
{
// ...
}
}
关于c# - 处理 Service Fabric 中的聚合异常,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44051306/