swcraft
swcraft

Reputation: 2112

Dependency injection of type having nested dependency

I want to create a type which contains another dependency.

The reason is so that I can make the controller rely on a Infrastructure wrapper with more abstracted functions which then actually access the data layer.

So here is the wrapper having dependency of dbcontext

public Repository(IdbContext context)
{
    _context = context;
}

The controller constructor:

private readonly Repository _repo;

public TheController(IRepository repo)
{
    _repo = repo;
}

In the Startup.cs, ConfigureServices:

services.AddDbContext<dbContext>(options =>         
    options.UseSqlServer(Configuration.GetConnectionString("dbContext")));
services.AddTransient<IRepository, Repository>();

In the Program.cs,

using (var scope = host.Services.CreateScope())
{
    var services = scope.ServiceProvider;
    var context = services.GetRequiredService<dbContext>();
    var _repo = services.GetRequiredService<IRepository>();
    ...
}

The GetRequiredService<IRepository>() fails with following Exception:

System.InvalidOperationException: 'Unable to resolve service for type 'namespace.Models.IdbContext' while attempting to activate 'namespace.Repositories.Repository'.'

Upvotes: 2

Views: 3710

Answers (2)

Nkosi
Nkosi

Reputation: 247098

Associate the IdbContext interface with the dbContext implementation.

Assuming

public class dbContext: DbContext, IdbContext  {
    //...
}

It is failing because it was not registered and the provider does not know what to initialized when injecting IdbContext into the repository.

services.AddDbContext<IdbContext, dbContext>(options =>         
    options.UseSqlServer(Configuration.GetConnectionString("dbContext")));
services.AddTransient<IRepository, Repository>();

Upvotes: 2

Shaun Luttin
Shaun Luttin

Reputation: 141512

You need to inject the same type that you register.

If you register a dbContext, then inject a dbContext.

services.AddDbContext<dbContext>(options => ...);

public Repository(dbContext context)
{
    _context = context;
}

If you register an IdbContext, then inject an IdbContext.

services.AddDbContext<IdbContext, dbContext>(options => ...);

public Repository(IdbContext context)
{
    _context = context;
}

Here is the latter option as a runnable demo:

https://github.com/shaunluttin/asp-net-core-db-context-interface-injection

Upvotes: 2

Related Questions