我正在尝试通过一个帮助程序函数发出 httpclient 请求,该函数将管理断路器波利策略。
我试着这样称呼它
var response = clientFactory.MakeRequest(() => client.GetAsync("/"));
在客户端工厂内部,我定义了断路器策略,并且我正在尝试使用该策略执行上面的 lambda,如下所示
public async Task<HttpResponseMessage> MakeRequest(Func<HttpResponseMessage> request)
{
var response = policy.ExecuteAsync(() => request.Invoke());
return response;
}
我对 Lambda 作为一个整体相当陌生,将其作为函数传递会变得更加混乱。如何配置函数和第一行代码以执行客户端并返回HttpResponseMessage
?我认为Task<HttpResponseMessage>
或Func<HttpResponseMessage>
不正确
我建议你阅读一些关于async/await(不是lambdas(的信息,因为这是理解如何实现它的关键。
https://learn.microsoft.com/en-us/dotnet/csharp/async
您正在使用异步编程,因此必须决定是要异步方法MakeRequest还是要同步方法。如果你想要同步(但是 - 不需要使用执行异步。我想,有 Execute(( 替代方案(简单的编写:
public HttpResponseMessage MakeRequest(Func<HttpResponseMessage> request)
{
var response = policy.ExecuteAsync(() => request.Invoke());
return await response;
}
如果你想要异步:
public async Task<HttpResponseMessage> MakeRequest(Func<HttpResponseMessage> request)
{
var response = policy.ExecuteAsync(() => request.Invoke());
return response;
}
public void MyMethodUsingAsync()
{
var responsePromises = MakeRequest(() => {...});
///do some job wich will be done before response is retrieved (not waiting for it); and if you need it - use await
var responseReceived = await responsePromises;
}
让我们从这一行开始:
var response = clientFactory.MakeRequest(() => client.GetAsync("/"));
如果client
是HttpClient
实例,则GetAsync
返回一个Task<HttpResponseMessage>
。因此,您作为参数传递给MakeRequest
的是一个返回Task<HttpResponseMessage>
的函数。在不定义自定义委托的情况下,您可以使用Func
类型来描述此意图:Func<Task<HttpResponseMessage>>
。
因此,您的MakeRequest
应该预见到这种参数,以便能够使用策略(或策略链(对其进行修饰。MakeRequest
的实际实现可以用许多不同的方式编写:
选项 1
- 按原样传递
request
ExecuteAsync
按 - 原样返回
ExecuteAsync
结果
public Task<HttpResponseMessage> MakeRequest(Func<Task<HttpResponseMessage>> request)
=> policy.ExecuteAsync(request);
选项 2
- 按原样传递
request
ExecuteAsync
- 等待
ExecuteAsync
的结果
public async Task<HttpResponseMessage> MakeRequest(Func<Task<HttpResponseMessage>> request)
=> await policy.ExecuteAsync(request);
选项 3
- 将函数传递给调用
request
的ExecuteAsync
- 按原样返回
ExecuteAsync
的结果
public Task<HttpResponseMessage> MakeRequest(Func<Task<HttpResponseMessage>> request)
=> policy.ExecuteAsync(() => request());
选项 4
- 将函数传递给调用
request
的ExecuteAsync
- 等待
ExecuteAsync
的结果
public async Task<HttpResponseMessage> MakeRequest(Func<Task<HttpResponseMessage>> request)
=> await policy.ExecuteAsync(() => request());
选项 5
- 将异步函数传递给等待
request
的ExecuteAsync
- 按原样返回
ExecuteAsync
的结果
public Task<HttpResponseMessage> MakeRequest(Func<Task<HttpResponseMessage>> request)
=> policy.ExecuteAsync(async () => await request());
选项 6
- 将异步函数传递给等待
request
的ExecuteAsync
- 等待
ExecuteAsync
的结果
public async Task<HttpResponseMessage> MakeRequest(Func<Task<HttpResponseMessage>> request)
=> await policy.ExecuteAsync(async () => await request());
尽管选项 1 是最简单的,但我建议使用选项 6
- 正如David Fowler(Microsoft的 ASP.NET 建筑师(所建议的那样,更喜欢
async
/await
而不是直接返回Task
- 即使 Polly
await
传递给ExecuteAsync
的传递的Func<Task<TResult>>
方法,它是一个实现细节,你不应该依赖这个