Вам доведеться робити цикл, і, якщо цикл буде, це зручніше перенести цикл в окрему функцію.
Я створив метод розширення для боротьби з цим. Він повертає список усіх внутрішніх винятків зазначеного типу, переслідуючи 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
. Мій виняток завжди є останнім на ланцюжку і не має власного внутрішнього винятку.