1

I have a unit of work class, which contains an ExpressionRepository. I want to replace it with an interface (IExpressionRepository) and bind it to ExpressionRepository with Ninject, but here's the problem: My ExpressionRepository expects a DbContext as a constructor parameter, but you can't define a constructor in an interface as far as I know, so I can't call this constructor without using the concrete implementation.

Here's the code as it stands now, without using an interface:

    private DbContext _dbContext;
    private ExpressionRepository _expressionRepository;

    public UnitOfWork(DbContext dbContext)
    {
        _dbContext = dbContext;
    }

    public ExpressionRepository ExpressionRepository
    {
        get { return _expressionRepository ?? (_expressionRepository = new ExpressionRepository(_dbContext)); }
    }

My best guess is to add a method like 'void setDataSource(Object dataSource)' to my interface, but is there a better way?

Tyler Durden
  • 2,031
  • 4
  • 20
  • 25

2 Answers2

0

Your question isn't entirely clear but if the problem is that you can't set up the DbContext at the point at which you're setting up your DI container (and thus can't inject the IExpressionRepository directly), then the solution to this is to inject a factory instead:

public interface IExpressionRepositoryFactory
{
    IExpressionRepository Create(string someIdentifier);
}

Here, someIdentifier is whatever information you need to set up the DbContext (e.g. a connection string or, better still, some implementation-independent ID that you can map to a connection string inside the factory). You can omit the parameter entirely if you know you don't need it (e.g. you're just going to read a config file).

Then, you inject the factory into whatever class needs the repository and you can specify someIdentifier as appropriate.

Usually what you'd then do is pass (inject) your repository into the unit of work, so the UoW isn't directly dependent upon the DbContext and just uses "whatever mechanism the repository has," whether that be a DbContext, a SqlClient or some other ORM.

If you're comfortable with always having a DbContext, you could just do the following instead - but this will mean that any repository implementation will always have to back onto a DbContext:

IExpressionRepository Create(DbContext context);

This still decouples the IExpressionRepository itself from the DbContext class - just not the factory interface.

Ant P
  • 24,820
  • 5
  • 68
  • 105
0

Use method binding if you don't want to use the factory approach mention by @Ant P:

Bind<IExpressionRepository>().ToMethod(context => new ExpressionRepository(GetMyDbContext()));

Or you can use the normal binding where your ExpressionRepository class takes DBContext as a parameter in its constructor and bind your DBContext:

 Bind<DBContext>().ToSelf().InRequestScope();
 Bind<IExpressionRepository>().To<ExpressionRepository>();

Check out this question, it has the same approach i guess :

How to handle DBContext when using Ninject

Community
  • 1
  • 1
sm_
  • 2,572
  • 2
  • 17
  • 34