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