微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

Polly IAsync 策略的通用接口 编译时错误运行时错误

如何解决Polly IAsync 策略的通用接口 编译时错误运行时错误

谁能告诉我为什么这不起作用?

我正在尝试创建一个通用接口来在 C# 中定义 Polly RetryPolicy 和 CircuitBreaker 策略,但出现编译错误

CS0029:无法将类型“Polly.Retry.AsyncRetryPolicy”隐式转换为“T”

类型 AsyncRetryPolicy 派生自 IAsyncPolicy 所以我不知道为什么这不起作用。

public interface IPollyPolicy<T> where T : IAsyncPolicy
{
    T PolicyAsync { get; }

    Task ExecuteAsync(Func<Task> operation,CancellationToken cancellationToken);

    Task<TResult> ExecuteAsync<TResult>(Func<Task<TResult>> operation,CancellationToken cancellationToken);
}

public class MyRetryPolicy<T> : IPollyPolicy<T> where T : IAsyncPolicy
{

    public T PolicyAsync { get; }

    public MyRetryPolicy(int retryCount = 3,int initialWaitMs = 3000,double factor = 3,bool fastFirst = true)
    {
        var delay = Backoff.ExponentialBackoff(TimeSpan.FromMilliseconds(initialWaitMs),retryCount: retryCount,factor: factor,fastFirst: fastFirst).ToList();


             // this line Throws the error: 
             PolicyAsync = Policy
            .Handle<sqlException>()
            .WaitAndRetryAsync(delay);

    }


public class MyCircuitBreakerPolicy<T> : IPollyPolicy<T> where T : IAsyncPolicy
{

    public T PolicyAsync { get; }

    public MyCircuitBreakerPolicy(int retryCount = 3,bool fastFirst = true)
    {
        PolicyAsync = Policy
            .Handle<sqlException>()
            .CircuitBreakerAsync(exceptionsAllowedBeforeBreaking: exceptionsAllowedBeforeBreaking,durationOfBreak: TimeSpan.FromSeconds(durationofBreakSeconds));
    }

然后使用工厂来消费这些:

public class PolicyFactory : IPolicyFactory
{
    public IAsyncPolicy GetAsync(PolicyType policyType)
    {
        switch (policyType)
        {
            case PolicyType.RetryPolicy:
                return new MyRetryPolicy(3,3000,3,true);
            case PolicyType.CircuitBreakerPolicy:
                return new MyCircuitBreakerPolicy(2,5);
        }

    }

}

任何帮助将不胜感激!

谢谢 安德鲁。

解决方法

如果你只是想摆脱编译时错误,那么你需要做的就是:

PolicyAsync = (T)Convert.ChangeType(Policy.Handle<Exception>().WaitAndRetryAsync(delay),typeof(T));

这里我们通过使用 Convert.ChangeType 将具体类型转换为泛型类型。

但是有一个问题:MyRetryPolicy 只能接受一种类型AsyncRetryPolicy

var policy = new MyRetryPolicy<AsyncRetryPolicy>();
Console.WriteLine(policy.PolicyAsync == null);

编译时错误

var policy = new MyRetryPolicy<AsyncRetryPolicy<HttpResponseMessage>>(); //cs3011

严重性代码描述项目文件行抑制状态 错误 CS0311 类型“Polly.Retry.AsyncRetryPolicy”不能用作泛型类型或方法“MyRetryPolicy”中的类型参数“T”。没有从“Polly.Retry.AsyncRetryPolicy”到“Polly.IAsyncPolicy”的隐式引用转换。 2021_03_05 c:\Users\pcsala\source\repos\2021_03_05\Program.cs 20 活动

运行时错误

var policy = new MyRetryPolicy<AsyncTimeoutPolicy>(); //InvalidCastException

未处理的异常。 System.InvalidCastException:对象必须实现 IConvertible。 在 System.Convert.ChangeType(Object value,Type conversionType,IFormatProvider provider) 在 System.Convert.ChangeType(Object value,Type conversionType)


更新:替代
您的具体类型不应接收类型参数。

public class MyRetryPolicy: IPollyPolicy<AsyncRetryPolicy>
{
    public AsyncRetryPolicy PolicyAsync { get; }
    ...
}

public class MyCircuitBreakerPolicy : IPollyPolicy<AsyncCircuitBreakerPolicy>
{
    public AsyncCircuitBreakerPolicy PolicyAsync { get; }
    ...
}

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。