如何处理AggregateException?在许多TPL或业务场景中,它确实很有用,但是处理是一个真正的痛苦。我定义了以下三个扩展来帮助我自己。它们可以这样使用:
try
{
throw new AggregateException(
new ArgumentException(),
new DivideByZeroException());
}
catch (AggregateException aex)
{
aex
.Handle((ArgumentException ex) =>
{
Console.WriteLine(ex.Message);
})
.Handle((DivideByZeroException ex) =>
{
Console.WriteLine(ex.Message);
throw ex;
})
.Throw<DivideByZeroException>()
.Throw<ArgumentException>()
.ThrowIfNonEmpty();
}这些方法是在AggregateException上定义的,并返回AggregateException,这样就可以将它们链接起来。
Handle为指定类型的每个内部异常实例调用一次参数委托,并返回一个AggregateException的新副本,而不包含那些已处理的异常。在委托中抛出的一个可选异常将添加到结果AggregateException中。
Throw方法尝试查找指定类型的第一个内部异常实例,并在找到时抛出它。你可以把他们锁在一起来决定优先权。
ThrowIfNonEmpty扩展了一个AggregateException,以便在InnerExceptions集合不是空时抛出它。
public static class AggregateExceptionExtensions
{
public static AggregateException Handle<TEx>(
this AggregateException source, Action<TEx> handler)
where TEx : Exception
{
var exceptions = source.Flatten().InnerExceptions.OfType<TEx>();
var handlerExceptions = new List<Exception>();
foreach (var exception in exceptions)
try
{
handler(exception);
}
catch (Exception ex)
{
handlerExceptions.Add(ex);
}
return new AggregateException(source.InnerExceptions
.Except(exceptions)
.Concat(handlerExceptions));
}
public static AggregateException Throw<TEx>(this AggregateException source)
{
var ex = source.InnerExceptions.FirstOrDefault(e => e is TEx);
if (ex != null)
throw ex;
return source;
}
public static void ThrowIfNonEmpty(this AggregateException source)
{
if (source.InnerExceptions.Any())
throw source;
}
}你能提出其他可能有用的窍门吗?
发布于 2016-09-04 04:07:15
我不认为只重新抛出特定类型的第一个/单个异常是个好主意。通常,当正确处理时,每个异常可能包含不同的错误数据,比如多个实体可能会发生实体验证错误,或者可能找不到多个文件等。如果您只选择第一个,那么您将不知道其余的情况,下次您将应用崩溃。
Handle和ThrowIfNonEmpty都很好,但是Throw非常有害。
此外,我会将Handle更改为Func<TEx, bool>:
public static AggregateException Handle<TEx>(
this AggregateException source, Func<TEx, bool> handler)
where TEx : Exception
{
var exceptions = source.Flatten().InnerExceptions.OfType<TEx>();
var handlerExceptions = new List<Exception>();
foreach (var exception in exceptions)
{
try
{
if (!handler(exception))
{
handlerExceptions.Add(exception);
}
}
catch (Exception ex)
{
handlerExceptions.Add(ex);
}
}
return new AggregateException(source.InnerExceptions
.Except(exceptions)
.Concat(handlerExceptions));
}因此,例如,我可以记录它,并且仍然可以说我没有通过返回false来处理它。
.Handle((ArgumentException ex) =>
{
Console.WriteLine(ex.Message);
return false;
})https://codereview.stackexchange.com/questions/120503
复制相似问题