繁体   English   中英

在尊重控制反转的同时,在 .NET Core 中使用依赖注入

[英]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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM