我有一个需要服务的 Controller ,所以我注入(inject)了它。该服务需要 HttpClient
所以我注入(inject)它。他们都需要 EF 上下文。
我确实添加了 HttpClient
在服务启动时。但是我有以下错误。
在Startup
:
services.AddHttpClient<IMyService, MyService>();
在MyService
类
private readonly HttpClient _httpClient;
private readonly ReadContext _readContext;
public MyService(HttpClient httpClient, ReadContext readContext)
{
_httpClient = httpClient;
_readContext = readContext;
}
在我的 Controller 中:
private readonly IMyService _myService;
public MyController(ReadContext ctx, IMyService myService)
{
_ctx = ctx;
_myService = myService;
}
错误:
System.InvalidOperationException: Cannot resolve scoped service 'MyApp.Backend.ReadContext' from root provider.
at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteValidator.ValidateResolution(Type serviceType, IServiceScope scope, IServiceScope rootScope)
at Microsoft.Extensions.DependencyInjection.ServiceProvider.Microsoft.Extensions.DependencyInjection.ServiceLookup.IServiceProviderEngineCallback.OnResolve(Type serviceType, IServiceScope scope)
at Microsoft.Extensions.DependencyInjection.ServiceLookup.ServiceProviderEngine.GetService(Type serviceType, ServiceProviderEngineScope serviceProviderEngineScope)
at Microsoft.Extensions.DependencyInjection.ServiceLookup.ServiceProviderEngineScope.GetService(Type serviceType)
at Microsoft.Extensions.DependencyInjection.ActivatorUtilities.GetService(IServiceProvider sp, Type type, Type requiredBy, Boolean isDefaultParameterRequired)
at lambda_method(Closure , IServiceProvider , Object[] )
at Microsoft.Extensions.Http.DefaultTypedHttpClientFactory`1.CreateClient(HttpClient httpClient)
当服务被注入(inject)到不需要 ReadContext
的 Controller 中时,情况并非如此。 ,这有效。这里似乎有一些解决循环。
更新
从评论中,我了解到 AddHttpClient<T>
创建 T
的实例与 HttpClient
具有相同的生命周期由 aspnet core 创建和管理,它比 DbContext
长lifetime 这是实际请求的生命周期。很公平。那么我该如何注入(inject) HttpClient
进入临时服务?
更新2
根据 blog我可以注入(inject) IHttpClientFactory
的实例在MyService
而不是使用 services.AddHttpClient();
.事实上,错误消失了。我将不得不做一些阅读以了解向工厂询问 HttpClient
的实例之间的区别。或注入(inject)一个。
最佳答案
将 MyService
注册为作用域:
services.AddScoped<IMyService, MyService>();
然后,只需使用 MyService
注册您的 HttpClient
:
services.AddHttpClient<MyService>();
您现在的做法是,MyService
是在单例范围内创建的,这使得无法像您的上下文一样注入(inject)范围内的依赖项。
或者,您可以注入(inject) IServiceProvider
并使用服务定位器反模式来获取上下文。它被称为反模式是有原因的,所以这不是解决问题的最佳方法,但如果您的服务是单例范围的,则没有其他方法:
public class MyService : IMyService
{
private readonly HttpClient _client;
private readonly IServiceProvider _services;
public MyService(HttpClient client, IServiceProvider services)
{
_client = client;
_services = services;
}
}
然后,稍后:
using (var scope = _services.CreateScope())
{
var context = scope.ServiceProvider.GetRequiredService<ReadContext>();
// do something
}
关于c# - 为什么我不能在需要相同上下文的 Controller 中注入(inject)需要 httpclient 和 EF 上下文的服务,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52780587/