简体   繁体   English

找到最内层异常的正确方法?

[英]Proper way to find the innermost exception?

I'm working with some classes which, when throwing, have a relatively deep InnerException tree. 我正在使用一些类,这些类在抛出时具有相对较深的InnerException树。 I'd like to log and act upon the innermost exception which is the one having the real reason for the problem. 我想记录并采取最内部的异常,这是具有问题真正原因的异常。

I'm currently using something similar to 我目前正在使用类似的东西

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

Is this the proper way to handle Exception trees? 这是处理异常树的正确方法吗?

I think you can get the innermost exception using the following code: 我认为你可以使用以下代码获得最内层的异常:

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

You could use the GetBaseException method. 您可以使用GetBaseException方法。 Very quick example: 很快的例子:

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());
}

In a word, yes. 总之,是的。 I cannot think of any significantly better or different way of doing it. 我无法想到任何明显更好或不同的方式。 Unless you wanted to add it as an extension method instead, but it's really six of one, half-a-dozen of the other. 除非你想把它作为一种扩展方法添加,但它实际上只有六个,另外六个。

There are exceptions that can have multiple root causes (eg AggregateException and ReflectionTypeLoadException ). 有些异常可能有多个根本原因(例如AggregateExceptionReflectionTypeLoadException )。

I created my own class to navigate the tree and then different visitors to either collect everything or just the root causes. 我创建了自己的来导航树,然后创建不同的访问者来收集所有内容或只是根本原因。 Sample outputs here . 此处输出示例。 Relevant code snippet below. 以下相关代码段。

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;
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM