'Dependency injection in unit of work pattern using repositories
I want to create a unit of work class that wraps around repositories in a similar way to this.
The problem I'm having is trying to implement dependency injection by replacing the generic repositories in the example with an IRepository interface. In the uow in the linked article they use getters to check if the repository is instantiated and if it isn't then instantiate it.
public GenericRepository<Department> DepartmentRepository
{
get
{
if (this.departmentRepository == null)
{
this.departmentRepository = new GenericRepository<Department>(context);
}
return departmentRepository;
}
}
Which is strongly coupled.
I can see two ways around this.
- Use constructor injection.
- Use setter injection.
The problem with 1 is that if I inject all the repositories I have to instantiate each repository even if I don't use them in that particular unit of work instance. Thus incurring the overhead of doing so. I was imagining using one, database-wide, unit of work class so this would lead to a lot of needless instantiating and a gigantic constructor.
The problem with 2 is that it would be easy to forget to set and end up with null reference exceptions.
Is there any sort of best practices in this scenario? And are there any other options I have missed?
I'm just getting in to dependency injection and have done all the research I can find on the topic but I may be missing something key.
Solution 1:[1]
Instead of injecting repository instances inject single factory object which will be responsible for creating those instances. Your getters will then use that factory.
Solution 2:[2]
My solution is UnitOfWork still responsible for creating Repository but I made a GetRepository() factory method in UnitOfWork to do that.
public interface IUnitOfWork : IDisposable
{
T GetRepository<T>() where T : class;
void Save();
}
public class UnitOfWork : IUnitOfWork
{
private Model1 db;
public UnitOfWork() : this(new Model1()) { }
public UnitOfWork(TSRModel1 dbContext)
{
db = dbContext;
}
public T GetRepository<T>() where T : class
{
var result = (T)Activator.CreateInstance(typeof(T), db);
if (result != null)
{
return result;
}
return null;
}
public void Save()
{
db.SaveChanges();
}
private bool disposed = false;
protected virtual void Dispose(bool disposing)
{
if (!this.disposed)
{
if (disposing)
{
db.Dispose();
}
}
this.disposed = true;
}
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
}
public class TestRepository : GenericRepository<Test>, ITestRepository
{
public TestRepository(Model1 db)
: base(db)
{
}
}
public class TestManager: ITestManager
{
private IUnitOfWork unitOfWork;
private ITestRepository testRepository;
public TestManager(IUnitOfWork unitOfWork)
{
this.unitOfWork = unitOfWork;
testRepository = unitOfWork.GetRepository<TestRepository>();
}
}
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 | Ladislav Mrnka |
| Solution 2 |
