Search code examples
c#dependency-injectionninjectrepository-patternunit-of-work

How do I use Dependency Injection with Unit of Work and Repositories in C#? (Not a web based App)


I see a lot of questions and answers on this topic, however the vast majority are dealing with ASP.Net or other web based applications and something called .InRequestScope. I have yet to find this method in Ninject with a Windows Application.

I have the usual Unit of Work (UoW) and Repository (Repo) classes and Interfaces, but I am wanting to inject the same DbContext into both, each time a UoW is run from the DIContainer. My code looks like this;

public class UnitOfWork : IUnitOfWork, IDisposable
{
    private readonly FinancialContext _context;

    private IAccountRepository _accountRepository;
    public IAccountRepository Accounts
    {
        get { return _accountRepository; }
    }

    UnitOfWork(IMyContext context, IAccountRepository accountRepository)
    {
        _context = context;
        _accountRepository = accountRepository;
    }

    public void SaveChanges()
    {
        _context.SaveChanges();
    }

    public void Dispose()
    {
        _context.Dispose();
    }
}

public class AccountRepository : Repository<Account>, IAccountRepository
{
    public AccountRepository(IMyContext context) : base(context) { }
}

The DIContainer holds the following associations;

Bind<IUnitOfWork>().To<UnitOfWork>().InTransientScope();
Bind<IUnitOfWorkFactory>().ToFactory();

Bind<IMyContext>().To<MyContext>().InSingletonScope();

Bind<IAccountTypeRepository>().To<AccountTypeRepository>().InTransientScope();

I'll come back to the .InSingletonScope();

The way I have seen people do this normally has been in the UoW Properties for each Repo to have code to this effect;

private IAccountRepository _accountRepository;
public IAccountRepository Accounts
{
    get 
    { 
         if(_accountRepository = null)
         {
             _accountRepository = new AccountRepository(_context);
         }
         return _accountRepository; 
    }
}

And remove the injected repositories from the Constructor, there by ensuring that each instance of a repository using the same _context.

However in my mind this breaks the Dependency Injection for this class. Is there a way to do this where each creation of a UoW like so;

public TestUnitOfWork(IUnitOfWorkFactory unitOfWork)
{
    using (var UoW = unitOfWork.Create())
    {
         Work done on UoW... 
    }
}

Currently the .InSingletonScope allows this, but is this keeping an instance of the context always open? Introducing the errors associated with not disposing a context properly?

Or is it better to create a Factory for the Repositories and give them a context parameter, then in the properties initialise it like so;

private IAccountRepository _accountRepository;
public IAccountRepository Accounts
{
    get 
    { 
         if(_accountRepository = null)
         {
             _accountRepository = RepositoryFactory.CreateAccountRepository(_context);
         }
         return _accountRepository; 
    }
}

Thanks in advance for any help!


Solution

  • The solution is the use Ninject's Extensions.Factory class and pass in an IAccountFactory.Create() to initialise a new object. This then uses the DI Container to resolve its dependencies and doesn't break the DI approach.