Jim*_*988 5 c# dependency-injection asp.net-core
在我的 .NET Core 控制台应用程序中,此行冻结:
services.GetRequiredService<ISomething>();
在下面的代码中:
interface ISomething { }
class Cool : ISomething
{
public Cool(IHttpClientFactory factory) { }
}
class Program
{
static async Task Main(string[] args)
{
var host = CreateHostBuilder(args).Build();
await host.StartAsync();
// Freezes here and maxes out memory
ISomething internalApiConnector = host.Services.GetRequiredService<ISomething>();
await host.RunAsync();
}
public static IHostBuilder CreateHostBuilder(string[] args) =>
Host.CreateDefaultBuilder(args)
.ConfigureServices((_, services) =>
{
services.AddHttpClient<IHttpClientFactory>();
services.AddSingleton<ISomething, Cool>();
});
}
Run Code Online (Sandbox Code Playgroud)
并最终耗尽内存并最终导致应用程序崩溃。我缺少什么?
笔记:
Cool构造函数没有运行,所以似乎没有什么东西在那里停止。解决方案(谢谢大家):
serviceCollection.AddHttpClient<IHttpClientFactory>();需要改为
serviceCollection.AddHttpClient();
和
.BuildServiceProvider()是多余的。
您遇到的是由注册引起的堆栈溢出异常AddHttpClient<IHttpClientFactory>。这会导致 MS.DI 无法检测到的循环依赖性,从而导致不幸的堆栈溢出。
要理解为什么会发生这种情况,您需要查看以下代码HttpClientBuilderExtensions:
builder.Services.AddTransient<TClient>(s =>
{
var httpClientFactory = s.GetRequiredService<IHttpClientFactory>();
var httpClient = httpClientFactory.CreateClient(builder.Name);
var typedClientFactory = s.GetRequiredService<ITypedHttpClientFactory<TClient>>();
return typedClientFactory.CreateClient(httpClient);
});
Run Code Online (Sandbox Code Playgroud)
如代码所示,调用会AddHttpClient<TClient>导致委托的注册。当调用该委托时,IHttpClientFactory就会解析一个问题。由此创建了IHttpClientFactory一个。HttpClient但是,就您而言,您指定了IHttpClientFactory,TClient有效地替换了原始IHttpClientFactory注册。这导致对s.GetRequiredService<IHttpClientFactory>()回调的调用自身,从而产生循环依赖和堆栈溢出。
你做错的是IHttpClientFactory作为TClient提供AddHttpClient<TClient>。AddHttpClient旨在注册一个以 aHttpClient作为直接依赖项的“客户端”类。例如:
services.AddHttpClient<GitHubApiClient>() // GitHubApiClient depends on HttpClient
Run Code Online (Sandbox Code Playgroud)
然而,你并不是唯一有过错的一方。微软应该做得更好,因为:
AddHttpClient<TClient>方法不会验证允许这种情况发生的先决条件。由于提供AddHttpClient抽象是没有意义的TClient,所以至少它应该阻止这种情况并抛出异常。此外,注册不TClient包含任何HttpClient构造函数依赖项的 a 是没有意义的,因此也应该避免这种情况。这意味着 Microsoft 堆栈还有改进的空间;-)
| 归档时间: |
|
| 查看次数: |
2986 次 |
| 最近记录: |