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!
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.