Enr*_*one 6 c# dependency-injection ioc-container .net-core asp.net-core
我对 ASP.NET 核心依赖注入容器有疑问。这个问题专门针对ASP.NET core 3.1。
基本上,我问自己,是否注入类型的HTTP客户端内部托管服务创建一个所谓的俘虏依赖于依赖注入的条款。
我试图描绘的场景如下:
public interface IStudentsApiClient
{
Task<IEnumerable<Student>> GetAll(CancellationToken cancellationToken);
}
public class StudentsApiClient: IStudentsApiClient
{
private readonly HttpClient _httpClient;
public StudentsApiClient(HttpClient httpClient)
{
_httpClient = httpClient ?? throw new ArgumentNullException(nameof(httpClient));
}
public async Task<IEnumerable<Student>> GetAll(CancellationToken cancellationToken)
{
// call a GET endpoint to retrieve all the students from a third party api...
}
}
public class StudentsPollingHostedService: BackgroundService
{
private readonly IStudentsApiClient _apiClient;
public StudentsPollingHostedService(IStudentsApiClient apiClient)
{
_apiClient = apiClient ?? throw new ArgumentNullException(nameof(apiClient));
}
protected override async Task ExecuteAsync(CancellationToken stoppingToken)
{
// do something using the IStudentsApiClient service
}
}
// code from Startup.cs
services.AddHttpClient<IStudentsApiClient, StudentsApiClient>(); // IStudentsApiClient is registered as transient
services.AddHostedService<StudentsPollingHostedService>(); // the hosted service is registered as a singleton
Run Code Online (Sandbox Code Playgroud)
在上面的代码中,我在IStudentsApiClient单例 ( StudentsPollingHostedService) 中注入了一个瞬态依赖( ),从而创建了一个俘虏依赖。
根据我的理解,这可能会完全损害 ASP.NET 核心 HTTP 客户端工厂实现的整个目的,其目的是在消费者每次请求时返回一个新的 HTTP 客户端。在上面的代码中,我们基本上在整个应用程序生命周期内在托管服务中捕获了一个 HTTP 客户端实例。
您是否同意这是一个实际问题?
我修复上述代码的想法是更改 ,StudentsApiClient以便IHttpClientFactory用于创建HttpClient每次GetAll调用的新实例:
public interface IStudentsApiClient
{
Task<IEnumerable<Student>> GetAll(CancellationToken cancellationToken);
}
public class StudentsApiClient: IStudentsApiClient
{
private readonly IHttpClientFactory _factory;
public StudentsApiClient(IHttpClientFactory factory)
{
_factory = factory ?? throw new ArgumentNullException(nameof(factory));
}
public async Task<IEnumerable<Student>> GetAll(CancellationToken cancellationToken)
{
var httpClient = _factory.CreateClient("students");
// call a GET endpoint to retrieve all the students from a third party api...
}
}
public class StudentsPollingHostedService: BackgroundService
{
private readonly IStudentsApiClient _apiClient;
public StudentsPollingHostedService(IStudentsApiClient apiClient)
{
_apiClient = apiClient ?? throw new ArgumentNullException(nameof(apiClient));
}
protected override async Task ExecuteAsync(CancellationToken stoppingToken)
{
// do something using the IStudentsApiClient service
}
}
// code from Startup.cs
services.AddHostedService<StudentsPollingHostedService>(); // the hosted service is registered as a singleton
services.AddHttpClient("students", c =>
{
// students HTTP client configuration goes here...
});
services.AddSingleton<IStudentsApiClient, StudentsApiClient>(); // IStudentsApiClient is now registered as a singleton
Run Code Online (Sandbox Code Playgroud)
这是否解决了代码的第一个版本(如果有)的问题?
对于所有对这个话题感兴趣的普通读者,在dotnet/runtime github 存储库上有基本相同的讨论。
看来这里讨论的问题是一个实际问题。
详情请看这里。
我目前的决定是避免使用类型化客户端方法并注入它IHttpClientFactory,以确保完全安全。
| 归档时间: |
|
| 查看次数: |
920 次 |
| 最近记录: |