When the built-in dependency injection functionality is trying to create a type, it tries to resolve all of the constructor parameters. If it can’t resolve one of the parameters, it’ll throw a variation of one of these exceptions:
- InvalidOperationException: Unable to resolve service for type <Type Name> while attempt to activate <Type Name>.
- ArgumentException: Cannot instantiate implementation type ‘Type Name’ for service type ‘Type Name’.
The error you get will depend on how you’re doing registration. First, I’ll show the solution. Then I’ll show a few different variations of the problem.
Solution
The simplest solution is to explicitly register the type. If that type has a primitive constructor parameter, then also tell it exactly how to create the type.
Here’s an example. Let’s say you have a class called JsonLogger with the following constructor:
public JsonLogger(string source)
Code language: C# (cs)
You’d need to explicitly register this type and specify how to create it:
//rest of adding services
builder.Services.AddSingleton<ILogger>(_ => new JsonLogger("web app"));
//rest of init code
Code language: C# (cs)
Encapsulate the primitive parameters
Consider encapsulating primitive parameters in a class. For example, let’s say you have the following constructor:
public JsonLogger(string source, bool debugEnabled, IUtility utility)
Code language: C# (cs)
Encapsulate the two primitive parameters (string and bool) in a new class:
//Pull the primitives into a new class
public class LoggerConfig
{
public string Source { get; set; }
public bool DebugEnabled { get; set; }
}
//Change the parameter to use the object
public JsonLogger(LoggerConfig config, IUtility utility)
Code language: C# (cs)
Then register all of the types:
//rest of adding services
builder.Services.AddSingleton<IUtility, JsonUtility>();
builder.Services.AddSingleton<LoggerConfig>(_ => new LoggerConfig()
{
Source = "web app",
DebugEnabled = true
});
builder.Services.AddSingleton<ILogger, JsonLogger>();
//rest of initialization code
Code language: C# (cs)
Cause 1 example – services.AddSingleton<ILogger, JsonLogger>()
When you’re registering the type and telling it what concrete type you want, and that type has a primitive parameter, like this:
//rest of adding services
builder.Services.AddSingleton<ILogger, JsonLogger>();
//rest of initialization code
Code language: C# (cs)
Then you’ll get this exception:
Some services are not able to be constructed (Error while validating the service descriptor ‘ServiceType: ILogger Lifetime: Singleton ImplementationType: JsonLogger’: Unable to resolve service for type ‘System.String’ while attempting to activate ‘JsonLogger’.)
You have to tell it how to construct the type, since it doesn’t know how to resolve the primitive constructor parameter.
Cause 2 example – services.AddSingleton<ILogger>
When you try to register the type without explicitly telling it what concrete type to resolve to, like this:
//rest of adding services
builder.Services.AddSingleton<ILogger>();
//rest of initialization code
Code language: C# (cs)
Then you’ll get the following exception:
ArgumentException: Cannot instantiate implementation type ‘ILogger’ for service type ‘ILogger’.
Cause 3 example – When you don’t register the type
Let’s say you have a controller that’s dependent on ILogger:
[ApiController]
[Route("[controller]")]
public class WeatherForecastController : ControllerBase
{
private readonly ILogger _logger;
public WeatherForecastController(ILogger logger)
{
_logger = logger;
}
//rest of class
}
Code language: C# (cs)
If you don’t register the type it’s dependent on (ILogger), then you’ll get the following exception:
InvalidOperationException: Unable to resolve service for type ‘ILogger’ while attempting to activate ‘Controllers.WeatherForecastController’.
Note: This is not Microsoft.Extensions.Logging.ILogger.