阻止 IHttpClientFactory 为处理程序创建 DI 范围

Pre*_*oky 5 c# dependency-injection asp.net-core

  1. 我正在使用名为 的作用域服务IOperationContextProvider来保存有关当前执行上下文的一些信息(称为OperationContext)。
  2. 每当我启动一个新的执行路径(不仅是 HTTP 请求,还有一些异步脉冲,例如队列消息、更改提要更改..)时,我都会创建一个专用的 DI 服务范围。
  3. 任何类都可以注入提供程序并有权访问此上下文(例如相关 ID)。

对于传出请求,我想配置将相关 ID 添加到传出 HTTP 标头,如下所示:

services.AddHttpClient<IMyClass, MyClass>((serviceProvider, httpClient) =>
{
    var contextProvider = serviceProvider.GetRequiredService<IOperationContextProvider>();
    var corrId = contextProvider.Context.CorrelationId;
    httpClient.DefaultRequestHeaders.Add("x-corr-id", corrId);
});
Run Code Online (Sandbox Code Playgroud)

但是,我无法执行此操作,因为 IHttpClientFactory 为其正在创建的每个处理程序创建范围,并且无法从 HTTP 客户端配置内部访问我的上下文。添加 HTTP 消息处理程序也是如此,它们也是在与处理程序相同的范围内创建的。

官方文档

为每个处理程序创建IHttpClientFactory一个单独的 DI 范围。处理程序可以自由依赖任何范围的服务。

有没有办法达到与 HttpClient 本身构建相同的范围?

我只找到了一种方法MyClass,我也注入了HttpClient,我也注入IOperationContextProvider并手动配置,但这HttpClient有点麻烦,因为它需要在任何地方完成:

public MyClass(HttpClient httpClient, IOperationContextProvider contextProvider)
{
    var corrId = contextProvider.Context.CorrelationId;
    httpClient.DefaultRequestHeaders.Add("x-corr-id", corrId);
    this._httpClient = httpClient;
}
Run Code Online (Sandbox Code Playgroud)

pok*_*oke 3

如果您绝对不希望 HttpClientFactory 创建服务范围,那么您可以通过属性禁用此HttpClientFactoryOptions.SuppressHandlerScope行为。不过,\xe2\x80\x99t 没有一个很好的 API 来配置它,所以你必须这样做:

\n\n
var httpClientBuilder = services.AddHttpClient<IMyClass, MyClass>(\xe2\x80\xa6);\nservices.Configure<HttpClientFactoryOptions>(httpClientBuilder.Name, options =>\n{\n    options.SuppressHandlerScope = true;\n});\n
Run Code Online (Sandbox Code Playgroud)\n\n

或者,您也可以直接创建委托处理程序,而不通过 DI:

\n\n
services.AddHttpClient<IMyClass, MyClass>(\xe2\x80\xa6)\n    .AddHttpMessageHandler(sp =>\n    {\n        var contextProvider = sp.GetService<IOperationContextProvider>()\n        return new MyHandlerWithoutDI(contextProvider);\n    });\n
Run Code Online (Sandbox Code Playgroud)\n