Tienes que hacer un bucle, y al tener que hacerlo, es más limpio mover el bucle a una función separada.
Creé un método de extensión para lidiar con esto. Devuelve una lista de todas las excepciones internas del tipo especificado, persiguiendo Exception.InnerException y AggregateException.InnerExceptions.
En mi problema particular, perseguir las excepciones internas fue más complicado de lo habitual, porque las excepciones las lanzaban los constructores de clases que se invocaban mediante la reflexión. La excepción que estábamos detectando tenía una InnerException de tipo TargetInvocationException, y las excepciones que realmente necesitábamos mirar estaban enterradas en lo profundo del árbol.
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;
}
}
El uso es bastante simple. Si, por ejemplo, desea saber si encontramos un
catch (Exception ex)
{
var myExes = ex.innerExceptions<MyException>();
if (myExes.Any(x => x.Message.StartsWith("Encountered my specific error")))
{
}
}
LibraryException -> LibraryException -> LibraryException -> MyException
. Mi excepción es siempre la última de la cadena y no tiene su propia excepción interna.