通过 Lambda Func 发出 Http 请求



我正在尝试通过一个帮助程序函数发出 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("/"));

如果clientHttpClient实例,则GetAsync返回一个Task<HttpResponseMessage>。因此,您作为参数传递给MakeRequest的是一个返回Task<HttpResponseMessage>的函数。在不定义自定义委托的情况下,您可以使用Func类型来描述此意图:Func<Task<HttpResponseMessage>>


因此,您的MakeRequest应该预见到这种参数,以便能够使用策略(或策略链(对其进行修饰。MakeRequest的实际实现可以用许多不同的方式编写:

选项 1

  • 按原样传递requestExecuteAsync
  • 原样返回ExecuteAsync结果
public Task<HttpResponseMessage> MakeRequest(Func<Task<HttpResponseMessage>> request)
=> policy.ExecuteAsync(request);

选项 2

  • 按原样传递requestExecuteAsync
  • 等待ExecuteAsync的结果
public async Task<HttpResponseMessage> MakeRequest(Func<Task<HttpResponseMessage>> request)
=> await policy.ExecuteAsync(request);

选项 3

  • 将函数传递给调用requestExecuteAsync
  • 按原样返回ExecuteAsync的结果
public Task<HttpResponseMessage> MakeRequest(Func<Task<HttpResponseMessage>> request)
=> policy.ExecuteAsync(() => request());

选项 4

  • 将函数传递给调用requestExecuteAsync
  • 等待ExecuteAsync的结果
public async Task<HttpResponseMessage> MakeRequest(Func<Task<HttpResponseMessage>> request)
=> await policy.ExecuteAsync(() => request());

选项 5

  • 将异步函数传递给等待requestExecuteAsync
  • 按原样返回ExecuteAsync的结果
public Task<HttpResponseMessage> MakeRequest(Func<Task<HttpResponseMessage>> request)
=> policy.ExecuteAsync(async () => await request());

选项 6

  • 将异步函数传递给等待requestExecuteAsync
  • 等待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
  • 即使 Pollyawait传递给ExecuteAsync的传递的Func<Task<TResult>>方法,它是一个实现细节,你不应该依赖这个

最新更新