簡體   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