Proper way to find the innermost exception?

前端 未结 4 1948
孤独总比滥情好
孤独总比滥情好 2021-02-08 06:16

I\'m working with some classes which, when throwing, have a relatively deep InnerException tree. I\'d like to log and act upon the innermost exception which is the one having th

4条回答
  •  予麋鹿
    予麋鹿 (楼主)
    2021-02-08 06:51

    There are exceptions that can have multiple root causes (e.g. AggregateException and ReflectionTypeLoadException).

    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(ex, visitor, aggregateException => aggregateException.InnerExceptions);
        TestComplexExceptionType(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(Exception ex, ExceptionVisitor visitor, Func> 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;
    }
    

提交回复
热议问题