Вы должны зацикливаться, и зацикливаясь, чистее будет переместить цикл в отдельную функцию.
Я создал метод расширения, чтобы справиться с этим. Он возвращает список всех внутренних исключений указанного типа, отслеживая Exception.InnerException и AggregateException.InnerExceptions.
В моей конкретной задаче погоня за внутренними исключениями была более сложной, чем обычно, потому что исключения создавались конструкторами классов, которые вызывались посредством отражения. Исключение, которое мы ловили, имело InnerException типа TargetInvocationException, и исключения, на которые мы действительно должны были смотреть, были погребены глубоко в дереве.
public static class ExceptionExtensions
{
public static IEnumerable<T> innerExceptions<T>(this Exception ex)
where T : Exception
{
var rVal = new List<T>();
Action<Exception> lambda = null;
lambda = (x) =>
{
var xt = x as T;
if (xt != null)
rVal.Add(xt);
if (x.InnerException != null)
lambda(x.InnerException);
var ax = x as AggregateException;
if (ax != null)
{
foreach (var aix in ax.InnerExceptions)
lambda(aix);
}
};
lambda(ex);
return rVal;
}
}
Использование довольно просто. Если, например, вы хотите знать, если мы столкнулись с
catch (Exception ex)
{
var myExes = ex.innerExceptions<MyException>();
if (myExes.Any(x => x.Message.StartsWith("Encountered my specific error")))
{
// ...
}
}