2010-01-18 21 views
7

Estoy trabajando con algunas clases que, al lanzar, tienen un árbol InnerException relativamente profundo. Me gustaría iniciar sesión y actuar sobre la excepción más interna, que es la que tiene la verdadera razón del problema.¿La forma correcta de encontrar la excepción más interna?

Actualmente estoy usando algo similar a

public static Exception getInnermostException(Exception e) { 
    while (e.InnerException != null) { 
     e = e.InnerException; 
    } 
    return e; 
} 

Es esta la forma correcta de manejar árboles excepción?

+0

duplicado posible de [Encuentra la más interna excepción sin necesidad de utilizar un bucle while?] (Http://stackoverflow.com/questions/3876456/find-the-inner-most-exception-without-using- a-while-loop) – DavidRR

+0

En todo caso, es el otro el duplicado, este es más antiguo y tiene la respuesta correcta como aceptada. –

+0

La edad de la pregunta no siempre es el criterio de gobierno para designar un duplicado. Por ejemplo, considere que la otra pregunta tiene más de diez veces el número de visitas que esta. Además, la respuesta aceptada refleja solo la opinión de la persona que hizo la pregunta. Y finalmente, tenga en cuenta que la [respuesta más votada] (http://stackoverflow.com/a/5792456/1497596) a la otra pregunta también ofrece 'GetBaseException()', pero luego indica sus limitaciones en algunas situaciones. – DavidRR

Respuesta

10

creo que se puede conseguir la excepción interna usando el siguiente código:

public static Exception getInnermostException(Exception e) { 
    return e.GetBaseException(); 
} 
+1

Gracias, tengo que leer más documentos de API antes de preguntar :) –

0

En una palabra, sí. No puedo pensar en ninguna manera significativamente mejor o diferente de hacerlo. A menos que quieras agregarlo como método de extensión, pero en realidad es seis de una, media docena de la otra.

3

Puede utilizar el método GetBaseException. ejemplo muy rápida:

try 
{ 
    try 
    { 
     throw new ArgumentException("Innermost exception"); 
    } 
    catch (Exception ex) 
    { 
     throw new Exception("Wrapper 1",ex); 
    } 
} 
catch (Exception ex) 
{ 
    // Writes out the ArgumentException details 
    Console.WriteLine(ex.GetBaseException().ToString()); 
} 
+0

+1, me gustó más la otra respuesta, así que es por eso que la acepté. –

+0

Bastante, no puedo discutir con eso :) Solo pensé en dar un ejemplo de código/arnés de prueba demostrándolo en acción. – AdaTheDev

0

hay excepciones que pueden tener múltiples causas fundamentales (por ejemplo AggregateException y ReflectionTypeLoadException).

Creé mi propio class para navegar por el árbol y luego diferentes visitantes recolectan todo o solo las causas principales. Salidas de muestra here. Pedazo de código relevante a continuación.

public void Accept(ExceptionVisitor visitor) 
{ 
    Read(this.exception, visitor); 
} 

private static void Read(Exception ex, ExceptionVisitor visitor) 
{ 
    bool isRoot = ex.InnerException == null; 
    if (isRoot) 
    { 
     visitor.VisitRootCause(ex); 
    } 

    visitor.Visit(ex); 
    visitor.Depth++; 

    bool isAggregateException = TestComplexExceptionType<AggregateException>(ex, visitor, aggregateException => aggregateException.InnerExceptions); 
    TestComplexExceptionType<ReflectionTypeLoadException>(ex, visitor, reflectionTypeLoadException => reflectionTypeLoadException.LoaderExceptions); 

    // aggregate exceptions populate the first element from InnerExceptions, so no need to revisit 
    if (!isRoot && !isAggregateException) 
    { 
     visitor.VisitInnerException(ex.InnerException); 
     Read(ex.InnerException, visitor); 
    } 

    // set the depth back to current context 
    visitor.Depth--; 
} 

private static bool TestComplexExceptionType<T>(Exception ex, ExceptionVisitor visitor, Func<T, IEnumerable<Exception>> siblingEnumerator) where T : Exception 
{ 
    var complexException = ex as T; 
    if (complexException == null) 
    { 
     return false; 
    } 

    visitor.VisitComplexException(ex); 

    foreach (Exception sibling in siblingEnumerator.Invoke(complexException)) 
    { 
     visitor.VisitSiblingInnerException(sibling); 
     Read(sibling, visitor); 
    } 

    return true; 
} 
Cuestiones relacionadas