edge-util/src/Microsoft.Azure.Devices.Edge.Util/ExceptionEx.cs (63 lines of code) (raw):

// Copyright (c) Microsoft. All rights reserved. namespace Microsoft.Azure.Devices.Edge.Util { using System; using System.Collections.ObjectModel; using System.Linq; using System.Reflection; using System.Runtime.InteropServices; public static class ExceptionEx { public static bool IsFatal(this Exception exception) { while (exception != null) { switch (exception) { // ReSharper disable once UnusedVariable case OutOfMemoryException ex: return true; // ReSharper disable once UnusedVariable case SEHException ex: return true; } // These exceptions aren't themselves fatal, but since the CLR uses them to wrap other exceptions, // we want to check to see whether they've been used to wrap a fatal exception. If so, then they // count as fatal. if (exception is TypeInitializationException || exception is TargetInvocationException) { exception = exception.InnerException; } else if (exception is AggregateException) { // AggregateExceptions have a collection of inner exceptions, which may themselves be other // wrapping exceptions (including nested AggregateExceptions). Recursively walk this // hierarchy. The (singular) InnerException is included in the collection. ReadOnlyCollection<Exception> innerExceptions = ((AggregateException)exception).InnerExceptions; if (innerExceptions.Any(ex => IsFatal(ex))) { return true; } break; } else if (exception is NullReferenceException) { break; } else { break; } } return false; } public static T UnwindAs<T>(this Exception exception) where T : Exception { switch (exception) { case T tException: return tException; case AggregateException aggregateException when aggregateException.InnerExceptions.Count == 1: return UnwindAs<T>(aggregateException.InnerException); default: return null; } } public static bool HasTimeoutException(this Exception ex) => ex != null && (ex is TimeoutException || HasTimeoutException(ex.InnerException) || (ex is AggregateException argEx && (argEx.InnerExceptions?.Select(e => HasTimeoutException(e)).Any(e => e) ?? false))); } }