/// <summary>
        /// Non-recursive method to get ALL payload messages associated with exception
        /// </summary>
        /// <param name="ex"></param>
        /// <returns></returns>
        internal static string AllMessages(this Exception ex)
        {
            ExceptionPayload payload       = ex.GetOrCreatePayload();
            StringBuilder    sbAllMessages = new StringBuilder();

            foreach (ExceptionProperty exceptionProperty in payload.ExceptionProperties)
            {
                if (exceptionProperty.Name.StartsWith(InternalPropertyNamePrefix))
                {
                    continue; // Our internal stuff
                }
                string strNameValuePair = String.Format("\"{0}\" = \"{1}\"", exceptionProperty.Name, exceptionProperty.Value);
                sbAllMessages.Combine(strNameValuePair, Utils.NewLine);
            }

            foreach (DictionaryEntry de in ex.Data)
            {
                if (de.Key.ToString().StartsWith(InternalPropertyNamePrefix))
                {
                    continue; // Our internal stuff
                }
                string message = String.Format("\"{0}\" = \"{1}\"", de.Key, de.Value);
                sbAllMessages.Combine(message, Utils.NewLine);
            }
            return(sbAllMessages.ToString());
        }
        internal static TException SetDirty <TException>(this TException ex, bool dirty) where TException : Exception
        {
            ExceptionPayload payload = ex.GetOrCreatePayload();

            payload.Dirty = dirty;
            return(ex);
        }
        public static TException Swallow <TException>(this TException ex) where TException : Exception
        {
            ExceptionPayload payload = ex.GetOrCreatePayload();

            if (LogExplicitlySwallowedExceptions)
            {
                Tracer.LogSwallowedException(ex);
            }

            payload.Dirty = false;
            return(ex);
        }
        internal static ExceptionPayload GetOrCreatePayload(this Exception ex)
        {
            ExceptionPayload obj = ex.Data[PayloadLabel] as ExceptionPayload;

            if (null != obj)
            {
                return(obj);
            }

            obj = new ExceptionPayload(ex);
            ex.Data[PayloadLabel] = obj;
            return(obj);
        }
        public static List <object> GetNamedProperty(this Exception ex, string name)
        {
            List <object>    res     = new List <object>();
            ExceptionPayload payload = ex.GetOrCreatePayload();

            foreach (ExceptionProperty exceptionProperty in payload.ExceptionProperties)
            {
                if (exceptionProperty.Name == name)
                {
                    res.Add(exceptionProperty.Value);
                }
            }
            return(res);
        }
        public static TException AddCorrelationId <TException>(this TException ex, Guid correlationId) where TException : Exception
        {
            ExceptionPayload payload        = ex.GetOrCreatePayload();
            bool             savedDirtyFlag = payload.Dirty;

            try
            {
                return(ex.AddNamedProperty(InternalExceptionExtensions.CorrelationIdLabel, correlationId));
            }
            finally
            {
                // Assigning of the Correlation Id happens for ALL exceptions and it should not make them dirty.
                payload.Dirty = savedDirtyFlag;
            }
        }
        public static TException SetInnerException <TException>(this TException ex, Exception innerException) where TException : Exception
        {
            Debug.Assert(null == ex.InnerException, "Attempt to override existing inner exception");

            if (ex == innerException)
            {
                Tracer.Error("Detected serious bug: attempt to set inner exception field to the outer exception reference");
                return(ex);
            }

            InternalExceptionExtensions.InnerExceptionFieldInfo.SetValue(ex, innerException);
            ExceptionPayload payload = ex.GetOrCreatePayload();

            payload.Dirty = true;
            return(ex);
        }
        public static TException AddNamedProperty <TException>(this TException ex, string name, object value) where TException : Exception
        {
            ExceptionPayload payload = ex.GetOrCreatePayload();

            ExceptionProperty exceptionProperty = new ExceptionProperty(name, value);

            // Deduplication
            if (payload.ExceptionProperties.Contains(exceptionProperty))
            {
                Tracer.Warning("Detected potential bug: attempt to add duplicated exception property: Name = {0}, Value = {1}" +
                               Environment.NewLine + Environment.StackTrace, exceptionProperty.Name, exceptionProperty.Value);
                return(ex);
            }

            payload.ExceptionProperties.Add(exceptionProperty);
            payload.Dirty = true;
            return(ex);
        }
        public static TException Trace <TException>(this TException ex, [CallerFilePath] string callerFilePath = "",
                                                    [CallerLineNumber] int callerLineNumber = 0, [CallerMemberName] string callerMemberName = "") where TException : Exception
        {
            ExceptionPayload payload = ex.GetOrCreatePayload();

            CodeLocation codeLocation = new CodeLocation(callerFilePath, callerLineNumber, callerMemberName);

            ex.AddNamedProperty("TraceLocation", codeLocation.ToString());

            if (!payload.Dirty)
            {
                Tracer.Debug("Detected potential bug: logging exception which has already been logged. Duplicate exception log follows.");
            }

            Tracer.LogException(ex);
            payload.Dirty = false;
            return(ex);
        }