Вам нужно зацикливать, и, если бы вы зацикливали, было бы проще переместить цикл в отдельную функцию.
Я создал метод расширения, чтобы справиться с этим. Он возвращает список всех внутренних исключений указанного типа, отслеживая 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")))
{
}
}
LibraryException -> LibraryException -> LibraryException -> MyException
. Мое исключение всегда является последним в цепочке и не имеет собственного внутреннего исключения.