Правильный способ найти самое внутреннее исключение?
Я работаю с некоторыми классами,которые при метании имеют относительно глубокое дерево InnerException. Я хотел бы войти и действовать по самому внутреннему исключению, которое имеет реальную причину проблемы.
в настоящее время я использую что-то подобное
public static Exception getInnermostException(Exception e) {
while (e.InnerException != null) {
e = e.InnerException;
}
return e;
}
это правильный способ обработки исключений деревья?
4 ответов
Я думаю, вы можете получить внутреннее исключение, используя следующий код:
public static Exception getInnermostException(Exception e) {
return e.GetBaseException();
}
можно использовать GetBaseException метод. Очень быстрый пример:
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());
}
одним словом, да. Я не могу придумать никакого значительно лучшего или другого способа сделать это. Если вы не хотите добавить его в качестве метода расширения, но на самом деле это шесть из одного, полдюжины других.
есть исключения, которые могут иметь несколько основных причин (например,AggregateException
и ReflectionTypeLoadException
).
Я создал свой собственный класс для навигации по дереву, а затем различные посетители либо собрать все или только первопричины. Образец выходов здесь. Соответствующий фрагмент кода ниже.
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;
}