[英]Usage of Dependency Injection in .NET Core while respecting Inversion of Control
我的目最终,我将拥有一个依赖于HttpClient
的 class 并且在阅读它之后,似乎处理其生命周期的一种理想方法是使用依赖注入,这导致我遇到了我的问题,这更具有一般性(所以如果你对 HttpClient 的看法不同,这不是问题的一部分)。
让我们假设呼叫是在以下 class 的帮助下进行的:
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 会很好,因为我也可以将它用于例如 mocking 服务,用于测试或在开发过程中更改某些行为。
Stack Overflow 上的其他帖子暗示我没有完全理解控制反转原则。 例如,如果我与 ASP.NET 控制器进行比较,其中也使用了依赖注入,它们会以某种方式“神奇地”接收传入的请求,而实际上并没有在代码中的任何地方直接调用。 我假设这是我必须去 go 的方向,但我不知道我该怎么做。 如果有人能阐明一些有帮助的原则。 另外,如果有一种简单的方法可以将答案放入罐中,那也会有所帮助。
如果您使用 DI,最好使用 DI 创建所有类并使用 ServiceProvider 获取 Class 的实例。
在您的示例中,如果您在 Programm 启动中使用 ASP 或某些软件,则在 startup.cs 中将您的类添加到服务中
public void ConfigureServices(IServiceCollection services)
{
services.AddHttpClient()
.AddSingleton<EndpointAHandler>()
}
现在你可以通过调用加载你的 EndpointAHandler
var endpointAHandler = serviceProvider.GetService<EndpointAHandler>();
在 ASP 上,您可以将 IServiceProvider 作为参数添加到 Controller 构造函数中,并使用 DI 获取服务提供商。
希望这可以帮助。
为了继续这种依赖注入模式,重要的问题不是“我如何调用 Fetch 方法?”。 而是“我需要从哪里调用 Fetch 方法?”
您在上面创建的大致是一个类型化的 HttpClient,您可能在查看 Microsoft 提供的 HttpClientFactory 文档时遇到过它; 它需要一个 HttpClient 实例,然后围绕该实例提供一组更严格控制的操作。
当你创建类似 class 库的东西时,消费应用程序有责任将该客户端注册到它自己的服务容器中,以便它可用于任何注入的依赖项,无论是在你的代码中还是暴露给客户端直接使用。 为了使之成为可能,一种常见的做法是为服务集合编写某种构建器或 static 扩展方法,以帮助更轻松地处理该注册:
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()
,然后注入您的组件的任何地方都可以利用它们。
你可以看到微软自己为自己的services.AddHttpClient()
in GitHub here: https://github.com/do.net/runtime/blob/master/src/libraries/Microsoft.Extensions.Http/src/DependencyInjection /HttpClientFactoryServiceCollectionExtensions.cs
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.