Musisz zapętlić, a pętla jest czystsza, aby przenieść pętlę do oddzielnej funkcji.
Stworzyłem metodę rozszerzenia, aby sobie z tym poradzić. Zwraca listę wszystkich wyjątków wewnętrznych określonego typu, ścigając Exception.InnerException i AggregateException.InnerExceptions.
W moim konkretnym problemie pogoń za wewnętrznymi wyjątkami było bardziej skomplikowane niż zwykle, ponieważ wyjątki były rzucane przez konstruktorów klas, które były wywoływane przez refleksję. Wyjątek, który łapaliśmy, miał wyjątek InnerException typu TargetInvocationException, a wyjątki, którym faktycznie musieliśmy się przyjrzeć, zostały zakopane głęboko w drzewie.
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;
}
}
Użycie jest dość proste. Jeśli na przykład chcesz wiedzieć, czy napotkaliśmy plik
catch (Exception ex)
{
var myExes = ex.innerExceptions<MyException>();
if (myExes.Any(x => x.Message.StartsWith("Encountered my specific error")))
{
}
}
LibraryException -> LibraryException -> LibraryException -> MyException
. Mój wyjątek jest zawsze ostatni w łańcuchu i nie ma własnego wewnętrznego wyjątku.