1

我正在尝试使用 Polly 库和 Fallback 策略执行请求并返回带有 2 个执行器的响应。到目前为止,这是我的代码:

private IExecuter primary;
private IExecuter secondary;
private readonly Policy _policy;
public Client()
{
    primary = new Executer("primary");
    secondary = new Executer("secondary");

    _policy = Policy
        .Handle<Exception>()
        .Fallback((request) => GetResponseFallback(request));
}

public Response Process(Request request)
{
    return _policy.Execute( GetResponse(request));
}

private Response GetResponse(Request request)
{
    return this.primary.Execute(request);
}

private Response GetResponseFallback(Request request)
{
    return secondary.Execute(request);
}

这段代码的问题是我不能在这一行上放一个 Request 参数: .Fallback((request) => GetResponseFallback(request));

由于错误,代码将无法编译:

“无法从 'System.Threading.CancellationToken' 转换为 'PollyPOC.Request'”

如何使代码编译并告诉回退策略该操作将接收Request到该操作的参数GetResponseFallback

4

1 回答 1

0

为了将数据传递给您的 Fallback 方法,您需要利用Context

为了简单起见,让我稍微简化一下您的实现,向您展示如何使用Context

private int GetResponse(int request)
{
    return request + 1;
}

private int GetResponseFallback(int request)
{
    return request + 2;
}

所以我只是摆脱了IExecuter,RequestResponse概念,以使示例代码尽可能简单。


要将数据传递给您GetResponseFallback,我们需要像这样更改参数:

private const string requestKey = "request"; 
private int GetResponseFallback(Context ctx)
{
    var request = (int)ctx[requestKey];
    return request + 2;
}

所以,我们已经requestContext. 现在我们需要以某种方式将该信息传递给GetResponseFallback调用。

好处是我们不需要修改GetResponse. 另一方面,我们需要Process像这样调整方法:

private int Process(int request)
{
    var contextData = new Dictionary<string, object> { { requestKey, request } };

    _policy = Policy<int>
        .Handle<Exception>()
        .Fallback((ctx) => GetResponseFallback(ctx), (_, __) => { });

    return _policy.Execute((_) => GetResponse(request), contextData);
}
  • 我们创建了一个contextData字典来存储输入参数
  • 我们使用了Fallback 的特殊重载,我们必须在其中定义两个委托:
    • 不幸的是,没有重载,我们只需要提供一个Action<Context> fallbackAction参数
public static FallbackPolicy Fallback(this PolicyBuilder policyBuilder, Action<Context> fallbackAction, Action<Exception, Context> onFallback)
  • 因为我们不想在里面做任何事情onFallback这就是为什么我这样定义(_,__) => { }
  • 我们调用了一个特殊的 Execute 重载,它的语法如下:
public void Execute(Action<Context> action, IDictionary<string, object> contextData)
  • 因为我们没有将 Context 参数GetResponse直接传递给,所以我们可以在这里使用丢弃运算符 (_) => GetResponse(...)

最后一件重要的事情:我必须将_policy变量类型更改Policy<int>为指示返回类型。


为了完整起见,这里是完整的源代码:

private static Policy<int> _policy;
static void Main(string[] args)
{
    Console.WriteLine(Process(1));
}

private const string requestKey = "request";
static int Process(int request)
{
    var contextData = new Dictionary<string, object> { { requestKey, request } };

    _policy = Policy<int>
        .Handle<Exception>()
        .Fallback((ctx) => GetResponseFallback(ctx), (_, __) => { });

    return _policy.Execute((_) => GetResponse(request), contextData);
}

static int GetResponse(int request)
{
    throw new Exception();
    return request + 1;
}

static int GetResponseFallback(Context ctx)
{
    var request = (int)ctx[requestKey];
    return request + 2;
}
于 2021-09-15T09:42:41.960 回答