/// <summary> /// Returns the <see cref="AggregateException"/> that is the root cause of this exception. /// </summary> public override Exception GetBaseException() { // Returns the first inner AggregateException that contains more or less than one inner exception // Recursively traverse the inner exceptions as long as the inner exception of type AggregateException and has only one inner exception Exception back = this; AggregateException backAsAggregate = this; while (backAsAggregate != null && backAsAggregate.InnerExceptions.Count == 1) { back = back.InnerException; backAsAggregate = back as AggregateException; } return(back); }
/// <summary> /// Flattens an <see cref="AggregateException"/> instances into a single, new instance. /// </summary> /// <returns>A new, flattened <see cref="AggregateException"/>.</returns> /// <remarks> /// If any inner exceptions are themselves instances of /// <see cref="AggregateException"/>, this method will recursively flatten all of them. The /// inner exceptions returned in the new <see cref="AggregateException"/> /// will be the union of all of the the inner exceptions from exception tree rooted at the provided /// <see cref="AggregateException"/> instance. /// </remarks> public AggregateException Flatten() { // Initialize a collection to contain the flattened exceptions. List <Exception> flattenedExceptions = new List <Exception>(); // Create a list to remember all aggregates to be flattened, this will be accessed like a FIFO queue List <AggregateException> exceptionsToFlatten = new List <AggregateException> { this }; Int32 nDequeueIndex = 0; // Continue removing and recursively flattening exceptions, until there are no more. while (exceptionsToFlatten.Count > nDequeueIndex) { // dequeue one from exceptionsToFlatten IList <Exception> currentInnerExceptions = exceptionsToFlatten[nDequeueIndex++].InnerExceptions; for (Int32 i = 0; i < currentInnerExceptions.Count; i++) { Exception currentInnerException = currentInnerExceptions[i]; if (currentInnerException == null) { continue; } AggregateException currentInnerAsAggregate = currentInnerException as AggregateException; // If this exception is an aggregate, keep it around for later. Otherwise, // simply add it to the list of flattened exceptions to be returned. if (currentInnerAsAggregate != null) { exceptionsToFlatten.Add(currentInnerAsAggregate); } else { flattenedExceptions.Add(currentInnerException); } } } return(new AggregateException(Message, flattenedExceptions)); }