/// <summary>
        /// Executes the specified operation with the specified retry policy.
        /// </summary>
        /// <typeparam name="T">Returns an arbitrary type.</typeparam>
        /// <param name="function">The function to execute.</param>
        /// <param name="policy">The retry policy to apply to the function.</param>
        /// <param name="context">The abstraction context to use.</param>
        /// <param name="logger">An ILogger object to log retry attempts.</param>
        /// <returns>
        /// Returns the value received from the execution of the function.
        /// </returns>
        public static async Task <OperationExecutionResult <T> > ExecuteOperationWithRetry <T>(Func <Task <T> > function, IRetryPolicy policy, IAbstractionContext context, ILogger logger)
        {
            Stopwatch stopwatch = new Stopwatch();

            stopwatch.Start();
            for (int attempt = 0; attempt < policy.MaxAttemptCount;)
            {
                try
                {
                    if (attempt > 0)
                    {
                        logger.LogMessage(string.Format(CultureInfo.InvariantCulture, "\r\nRetrying Operation because previous attempt resulted in error.  Current Retry attempt: {0}\r\n\r\n", attempt),
                                          Severity.Informational,
                                          Verbosity.Detailed);
                    }
                    context.CancellationToken.ThrowIfCancellationRequested();
                    T result = await function();

                    attempt++;
                    return(new OperationExecutionResult <T>(result, stopwatch.Elapsed, attempt));
                }
                catch (Exception e)
                {
                    attempt++;
                    var retryParams = policy.GetRetryParameters(attempt, e);
                    //Log
                    if (retryParams.ShouldRetry)
                    {
                        context.CancellationToken.WaitForInterval(retryParams.WaitTime);
                    }
                    else
                    {
                        logger.LogMessage(string.Format(CultureInfo.InvariantCulture, "\r\nOperation attempt failed because of the following error:: {0}\r\n\r\n", e.Message),
                                          Severity.Informational,
                                          Verbosity.Detailed);
                        return(new OperationExecutionResult <T>(e, stopwatch.Elapsed, attempt));
                    }
                }
            }
            throw new InvalidOperationException("Should not reach here. Bug in retry policy implementation");
        }