首页 > 解决方案 > 执行 Polly 策略时如何包含 return 语句?

问题描述

下面是我在 C# Windows 应用程序中的代码,其中处理了与 Oracle、FTP 和空引用异常的连接:

public Result Execute()
{
    Result result = null;
    string errorMessage = string.Empty;

    var retryTimes = 1000;
    var retryableErrorCodes = new[] { "ORA-03113", "ORA-03114", "ORA-12543",
        "ORA-12170", "ORA-12154", "ORA-12541", "ORA-12560", "ORA-03135",
        "Connection request timed out" };
    var retryExceptionError = new[] { "Object reference not set to an instance of an object" };

    RetryPolicy retryPolicyFTP = Policy
        .Handle<Xceed.Ftp.FtpInvalidStateException>().Or<Xceed.Ftp.FtpIOException>()
        .WaitAndRetry(retryTimes, _ => TimeSpan.FromSeconds(1));

    RetryPolicy retryPolicyOracle = Policy
        .Handle<OracleException>(ex => retryableErrorCodes.Any(errorCode => ex.Message.ToString().Contains(errorCode)))
        .WaitAndRetry(retryTimes, _ => TimeSpan.FromSeconds(1));

    RetryPolicy retryException = Policy
        .Handle<Exception>(ex => retryExceptionError.Any(errorCode => ex.Message.ToString().Contains(errorCode)))
        .WaitAndRetry(retryTimes, _ => TimeSpan.FromSeconds(1));

    Policy.Wrap(retryPolicyFTP, retryPolicyOracle, retryException).Execute(() =>
    {
        //few lines of C# Code like fetching details from Database
        if(some condition)
        {
            //Some Operations
            return new Result(ResultType.Failure, "This function has Failed");
        }
        if(some other condition)
        {
            //Some Operations
            return new Result(ResultType.Success, "This function is Successful");
        }
        //Some more lines of C# Code
    });
    return Result.Successful;
}

使用这段代码,我不能return在函数中间使用关键字,因为 Polly 框架不允许这样做。

您能否建议return在函数中间处理关键字的更好方法是什么?

标签: c#polly

解决方案


在 Polly 中,您可以为方法和函数定义装饰器。

在方法的情况下,重试策略应定义如下:

RetryPolicy retryPolicyFTP = Policy
    .Handle<Xceed.Ftp.FtpInvalidStateException>().Or<Xceed.Ftp.FtpIOException>()
    .WaitAndRetry(retryTimes, _ => TimeSpan.FromSeconds(1));

如果是函数,重试策略应定义如下:

RetryPolicy<Result> retryPolicyFTP = Policy<Result>
    .Handle<Xceed.Ftp.FtpInvalidStateException>().Or<Xceed.Ftp.FtpIOException>()
    .WaitAndRetry(retryTimes, _ => TimeSpan.FromSeconds(1));

您也应该在这里发现<Result>lhs 和 rhs 上的部分。


有了这些知识,您的方法可以这样重写:

public Result Execute()
{
    Result result = null;
    string errorMessage = string.Empty;

    var retryTimes = 1000;
    var retryableErrorCodes = new[] { "ORA-03113", "ORA-03114", "ORA-12543", "ORA-12170", "ORA-12154", "ORA-12541", "ORA-12560", "ORA-03135", "Connection request timed out" };
    var retryExceptionError = new[] { "Object reference not set to an instance of an object" };

    RetryPolicy<Result> retryPolicyFTP = Policy<Result>
        .Handle<Xceed.Ftp.FtpInvalidStateException>().Or<Xceed.Ftp.FtpIOException>()
        .WaitAndRetry(retryTimes, _ => TimeSpan.FromSeconds(1));

    RetryPolicy<Result> retryPolicyOracle = Policy<Result>
        .Handle<OracleException>(ex => retryableErrorCodes.Any(errorCode => ex.Message.ToString().Contains(errorCode)))
        .WaitAndRetry(retryTimes, _ => TimeSpan.FromSeconds(1));

    RetryPolicy<Result> retryException = Policy<Result>
        .Handle<Exception>(ex => retryExceptionError.Any(errorCode => ex.Message.ToString().Contains(errorCode)))
        .WaitAndRetry(retryTimes, _ => TimeSpan.FromSeconds(1));

    Result res = Policy.Wrap(retryPolicyFTP, retryPolicyOracle, retryException).Execute(() =>
    {
        if (some condition)
        {
            return new Result(ResultType.Failure, "This function has Failed");
        }
        if (some other condition)
        {
            return new Result(ResultType.Success, "This function is Successful");
        }
        return Result.Successful;
    });
    return res;
}

因为你Execute必须返回 aResult这就是为什么Result.Successful可以在Execute块内移动。


我还建议像这样分开策略声明和执行:

public Result Execute()
{
    ...

    var strategy = Policy.Wrap(retryPolicyFTP, retryPolicyOracle, retryException)
    return strategy.Execute(() =>
    {
        if (some condition)
        {
            return new Result(ResultType.Failure, "This function has Failed");
        }
        if (some other condition)
        {
            return new Result(ResultType.Success, "This function is Successful");
        }
        return Result.Successful;
    });
}

推荐阅读