/// <summary>
        /// Runs an action and catches any exceptions thrown
        /// wrapping and rethrowing them as a <see cref="SolidDnaException"/>
        /// </summary>
        /// <param name="action">The action to run</param>
        /// <param name="errorTypeCode">The <see cref="SolidDnaErrorTypeCode"/> to wrap the exception in</param>
        /// <param name="errorCode">The <see cref="SolidDnaErrorCode"/> to wrap the exception in</param>
        /// <param name="errorDescription">The description of the error if thrown</param>
        public static void Wrap(Action action, SolidDnaErrorTypeCode errorTypeCode, SolidDnaErrorCode errorCode, string errorDescription)
        {
            try
            {
                action();
            }
            catch (Exception ex)
            {
                // Create the SolidDNA exception
                var error = new SolidDnaException(SolidDnaErrors.CreateError(
                                                      errorTypeCode,
                                                      errorCode,
                                                      errorDescription), ex);

                // If it should just be logged and ignored, log it
                if (SolidDnaEnvironment.LogAndIgnoreUncaughtExceptions)
                {
                    // Log the error
                    Logger.Log($"SolidDNA Exception created. {error.SolidDnaError?.ToString()}");
                    if (error.InnerException != null)
                    {
                        Logger.Log($"Inner Exception: { error.InnerException.GetErrorMessage()}");
                    }
                }
                // Otherwise, throw
                else
                {
                    throw error;
                }
            }
        }
        /// <summary>
        /// Runs a function and catches any exceptions thrown,
        /// wrapping and rethrowing them as a <see cref="SolidDnaException"/>
        /// </summary>
        /// <param name="func">The function to run</param>
        /// <param name="errorTypeCode">The <see cref="SolidDnaErrorTypeCode"/> to wrap the exception in</param>
        /// <param name="errorCode">The <see cref="SolidDnaErrorCode"/> to wrap the exception in</param>
        /// <param name="errorDescription">The description of the error if thrown</param>
        public static T Wrap <T>(Func <T> func, SolidDnaErrorTypeCode errorTypeCode, SolidDnaErrorCode errorCode, string errorDescription)
        {
            try
            {
                return(func());
            }
            catch (Exception ex)
            {
                // Create the SolidDNA exception
                var error = new SolidDnaException(SolidDnaErrors.CreateError(
                                                      errorTypeCode,
                                                      errorCode,
                                                      errorDescription), ex);

                // If it should just be logged and ignored, log it
                if (SolidDnaEnvironment.LogAndIgnoreUncaughtExceptions)
                {
                    // Log the error
                    Logger.LogCriticalSource($"SolidDNA Exception created. {error.SolidDnaError?.ToString()}");
                    if (error.InnerException != null)
                    {
                        Logger.LogCriticalSource($"Inner Exception: { error.InnerException.GetErrorMessage()}");
                    }

                    return(default(T));
                }
                // Otherwise, throw
                else
                {
                    throw error;
                }
            }
        }
        /// <summary>
        /// Runs a task and catches any exceptions thrown
        /// wrapping and rethrowing them as a <see cref="SolidDnaException"/>
        ///
        /// Returns the result of the task
        /// </summary>
        /// <param name="task">The task to run</param>
        /// <param name="errorTypeCode">The <see cref="SolidDnaErrorTypeCode"/> to wrap the exception in</param>
        /// <param name="errorCode">The <see cref="SolidDnaErrorCode"/> to wrap the exception in</param>
        /// <param name="errorDescription">The description of the error if thrown</param>
        public static async Task <T> WrapAwait <T>(Func <Task <T> > task, SolidDnaErrorTypeCode errorTypeCode, SolidDnaErrorCode errorCode, string errorDescription)
        {
            try
            {
                return(await task());
            }
            catch (Exception ex)
            {
                // Create the SolidDNA exception
                var error = new SolidDnaException(SolidDnaErrors.CreateError(
                                                      errorTypeCode,
                                                      errorCode,
                                                      errorDescription), ex);

                // If it should just be logged and ignored, log it
                if (SolidDnaEnvironment.LogAndIgnoreUncaughtExceptions)
                {
                    // Log the error
                    Logger.Log($"SolidDNA Exception created. {error.SolidDnaError?.ToString()}");
                    if (error.InnerException != null)
                    {
                        Logger.Log($"Inner Exception: { error.InnerException.GetErrorMessage()}");
                    }

                    // Return a default object
                    return(default(T));
                }
                // Otherwise, throw it up
                else
                {
                    throw error;
                }
            }
        }