我的目标是使用.NET Core编写一个使用REST API的库。为此,我有几个类来管理对不同端点的调用以及排队。最终,我将有一个依赖于HttpClient
的类,并且在阅读它之后,似乎似乎很需要处理其生命周期的方法是使用依赖项注入,这导致了我的问题,这更笼统。如果您对HttpClient的看法有所不同,那不属于问题的一部分。
让我们假设通过以下类的帮助进行呼叫:
using System;
using System.Net.Http;
using System.Text.Json;
using System.Threading.Tasks;
namespace ProducerConsumer
{
internal class EndpointAHandler
{
private readonly HttpClient _httpClient;
public EndpointAHandler(HttpClient httpClient)
{
_httpClient = httpClient ?? throw new ArgumentNullException(nameof(httpClient));
}
public async Task<JsonDocument> Fetch(Command command)
{
return await JsonDocument.ParseAsync(await _httpClient.GetStreamAsync((string)command.Parameters["url"]));
}
}
}
所以我想做的是依赖注入HttpClient
服务,这可以通过调用AddHttpClient()
到我的服务或注入IHttpClientFactory
(基于.Net Core Tutorials)来完成。
我现在遇到的问题是我不知道如何实际调用Fetch()
方法,因为我无法使用new手动创建它的实例。另外,使用服务定位器模式并不是真正的选择,因为它被视为反模式。因此,看来我从根本上了解一些错误。使用DI会很好,因为我也可以将其用于例如用于测试或在开发过程中更改某些行为的模拟服务。
[Stack Overflow上的其他帖子提示我不完全了解控制原理的反转。如果我比较例如在还使用依赖注入的ASP.NET控制器中,它们以某种方式“神奇地”接收了传入的请求,而没有实际在代码中的任何位置直接被调用。我认为这是我必须走的方向,但是我不知道如何做到这一点。如果有人可以阐明一些有帮助的原则。另外,如果有一种简单的方法将答案付诸实践,那也将有所帮助。
[为了继续这种依赖关系注入模式,重要的问题是更少的“我如何调用Fetch方法?”而是“我需要从哪里调用Fetch方法?”
您在上面创建的内容大致是一个类型化的HttpClient,您可能会在浏览Microsoft提供的the HttpClientFactory documentation时碰到的;它需要一个HttpClient实例,然后围绕该实例提供一组受更严格控制的操作。
[当您创建类库之类的内容时,消费应用程序有责任将该客户端注册到其自己的服务容器中,以便该客户端可用于其中的任何注入的依赖项,无论是在代码内还是要暴露给客户直接使用。为了使之成为可能,一种常见的做法是为服务集合编写某种构建器或静态扩展方法,以帮助简化注册过程:
public static class MyLibraryServiceExtensions
{
public static IServiceCollection AddMyLibrary(this IServiceCollection services)
{
if (services == null)
{
throw new ArgumentNullException(nameof(services));
}
services.AddHttpClient<IMyTypedClient, MyTypedClient>();
services.AddTransient<ISomeOtherDependency, SomeOtherDependency>();
// whatever else you need to register
return services;
}
}
使用此选项,使用者可以在启动或合成根期间执行services.AddMyLibrary()
,然后在您的组件被注入的任何位置都可以利用它们。
[您可以在此处看到Microsoft为自己的services.AddHttpClient()
而自己做的事情:https://github.com/dotnet/runtime/blob/master/src/libraries/Microsoft.Extensions.Http/src/DependencyInjection/HttpClientFactoryServiceCollectionExtensions.cs
如果使用DI,最好使用DI创建所有类,并使用ServiceProvider获取类的实例。
在您的示例中,将类添加到服务中,如果您在Programm启动时使用ASP或某些软件,则将它们添加到startup.cs中。>
public void ConfigureServices(IServiceCollection services) { services.AddHttpClient() .AddSingleton<EndpointAHandler>() }
现在您可以通过调用]加载EndpointAHandler。
var endpointAHandler = serviceProvider.GetService<EndpointAHandler>();
在ASP上,您可以将IServiceProvider作为参数添加到Controller构造函数中,并使用DI获取服务提供者。
希望这会有所帮助。