Asp.Net Core: some services are not able to be constructed
I'm a newbie in Asp.Net Core 3.1 and I'm studying DI(Dependency injection)
I have some service to test the lifetime of DI like transient, scope and singleton as below:
public interface IOperation
{
string GenGuid();
}
public interface IOperationTrans: IOperation
{
}
public interface IOperationScope: IOperation
{
}
public interface IOperationSingleton: IOperation
{
}
public class Operation : IOperationTrans, IOperationScope, IOperationSingleton
{
public string GuideRandom;
public Operation()
{
GuideRandom = Guid.NewGuid().ToString();
}
public string GenGuid()
{
return GuideRandom;
}
}
And I created another service with name IHumanService
as below:
public interface IHumanService
{
string GetTrans();
string GetScope();
string GetSingleton();
}
public class HumanService : IHumanService
{
private readonly IOperationTrans operationTrans;
private readonly IOperationScope operationScope;
private readonly IOperationSingleton operationSingleton;
public HumanService(IOperationTrans operationTrans, IOperationScope operationScope, IOperationSingleton operationSingleton)
{
this.operationTrans = operationTrans;
this.operationScope = operationScope;
this.operationSingleton = operationSingleton;
}
public string GetScope()
{
return operationScope.GenGuid();
}
public string GetSingleton()
{
return operationSingleton.GenGuid();
}
public string GetTrans()
{
return operationTrans.GenGuid();
}
public string GetTrans1()
{
return operationTrans.GenGuid();
}
}
And I register them in Startup.cs
as below:
public void ConfigureServices(IServiceCollection services)
{
services.AddTransient<IOperationTrans, Operation>();
services.AddScoped<IOperationScope, Operation>();
services.AddSingleton<IOperationSingleton, Operation>();
services.AddSingleton<IHumanService, HumanService>();
services.AddControllersWithViews();
}
Finally, I use them in my controller as below:
public class HomeController : Controller
{
private readonly IOperationTrans operationTrans;
private readonly IOperationScope operationScope;
private readonly IOperationSingleton operationSingleton;
private readonly IHumanService humanService;
public HomeController(IOperationTrans operationTrans, IOperationScope operationScope, IOperationSingleton operationSingleton, IHumanService humanService = null)
{
this.operationTrans = operationTrans;
this.operationScope = operationScope;
this.operationSingleton = operationSingleton;
this.humanService = humanService;
}
public IActionResult Index()
{
DIModel model = new DIModel();
model.TransProperty = operationTrans.GenGuid();
model.TransProperty1 = humanService.GetTrans();
model.ScopeProperty = operationScope.GenGuid();
model.ScopeProperty1 = humanService.GetScope();
model.SingletonProperty = operationSingleton.GenGuid();
model.SingletonProperty1 = humanService.GetSingleton();
return View(model);
}
}
When I run the project I got an error : AggregateException: Some services are not able to be constructed
An error occurred while starting the application.
AggregateException: Some services are not able to be constructed (Error while validating the service descriptor 'ServiceType: LearnDIExample.BSL.Human.IHumanService Lifetime: Singleton ImplementationType: LearnDIExample.BSL.Human.HumanService': Cannot consume scoped service 'LearnDIExample.BSL.Operation.IOperationScope' from singleton 'LearnDIExample.BSL.Human.IHumanService'.)
Microsoft.Extensions.DependencyInjection.ServiceProvider..ctor(IEnumerable<ServiceDescriptor> serviceDescriptors, ServiceProviderOptions options)
InvalidOperationException: Error while validating the service descriptor 'ServiceType: LearnDIExample.BSL.Human.IHumanService Lifetime: Singleton ImplementationType: LearnDIExample.BSL.Human.HumanService': Cannot consume scoped service 'LearnDIExample.BSL.Operation.IOperationScope' from singleton 'LearnDIExample.BSL.Human.IHumanService'.
Microsoft.Extensions.DependencyInjection.ServiceLookup.ServiceProviderEngine.ValidateService(ServiceDescriptor descriptor)
AggregateException: Some services are not able to be constructed (Error while validating the service descriptor 'ServiceType: LearnDIExample.BSL.Human.IHumanService Lifetime: Singleton ImplementationType: LearnDIExample.BSL.Human.HumanService': Cannot consume scoped service 'LearnDIExample.BSL.Operation.IOperationScope' from singleton 'LearnDIExample.BSL.Human.IHumanService'.)
Microsoft.Extensions.DependencyInjection.ServiceProvider..ctor(IEnumerable<ServiceDescriptor> serviceDescriptors, ServiceProviderOptions options)
Microsoft.Extensions.DependencyInjection.ServiceCollectionContainerBuilderExtensions.BuildServiceProvider(IServiceCollection services, ServiceProviderOptions options)
Microsoft.Extensions.DependencyInjection.DefaultServiceProviderFactory.CreateServiceProvider(IServiceCollection containerBuilder)
Microsoft.Extensions.Hosting.Internal.ServiceFactoryAdapter<TContainerBuilder>.CreateServiceProvider(object containerBuilder)
Microsoft.Extensions.Hosting.HostBuilder.CreateServiceProvider()
Microsoft.Extensions.Hosting.HostBuilder.Build()
LearnDIExample.Program.Main(string[] args) in Program.cs
+
CreateHostBuilder(args).Build().Run();
I really difficult to understand about DI, How can I resolve it?
-
T0
Tran Quang Hung Apr 16 2021
As your code, I can understand that:
IHumanService
is parent service it uses other services asIOperationTrans
IOperationScope
IOperationSingleton
(three services are children)=> You are registered for parent service is
Singleton
lifetime.=> For 3 services contain both
Singleton
,Scope
andTransient
lifetimes.But dependency injection is NOT alow:
- Case 1: Parent use
Singleton
and children useScope
.- Case 2: Parent use
Scope
and children useSingleton
.SOLUTION
Case 1: Change children from Scope to Singleton or Transient
public void ConfigureServices(IServiceCollection services) { //.............. services.AddSingleton<IOperationScope, Operation>(); OR services.AddTransient<IOperationScope, Operation>(); //.............. }
Case 2: Change service parent from Singleton to Scope or Transient
public void ConfigureServices(IServiceCollection services) { //.............. services.AddTransient<IHumanService, HumanService>(); OR services.AddScoped<IHumanService, HumanService>(); //.............. }
I hope it useful for you!!!
* Type maximum 2000 characters.
* All comments have to wait approved before display.
* Please polite comment and respect questions and answers of others.