Reputation: 5521
I've implemented my UnitOfWork so that it keeps references to all repositories.
public interface IUnitOfWork
{
void Commit();
void RollBack();
}
public interface IMyUnitOfWork : IUnitOfWork
{
IFooRepository Foos { get; }
IBarRepository Bars { get; }
// Other repositories ...
}
Note that the repositories implements a generic type of repository interface.
public interface IFooRepository : IRepository<Entities.Foo>
{
// FooRepository specific methods goes here.
}
public interface IRepository<T> : IRepository
where T : class
{
}
Now how can I inject these repository to my UnitOfWork. Of course I want them with a lazy loading behavior. For example:
public class ConcreteUnitOfWork : IMyUnitOfWork
{
private readonly IUnityContainer unityContainer;
private IFooRepository fooRepository;
public ConcreteUnitOfWork(IUnityContainer unityContainer)
{
this.repositoryFactory = repositoryFactory;
}
public IFooRepository Foos
{
get
{
return this.fooRepository ??
(this.fooRepository = unityContainer.Resolve<IFooRepository>());
}
}
}
I know passing the Unity container to the UnitOfWork is incorrect but what pattern would you offer to solve this issue?
You may mention that I shouldn't keep the repository references in the UnitOfWork but please suppose a service class which needs several repositories. With this design I can just pass the UnitOfWork as the constructor parameter (Constructor Injection) to the service class, but if I didn't keep the repository references in UnitOfWork, I would have to pass all needed repositories as constructor parameters and you know what it leads to.
-- UPDATE --
Please let me know if I'm absolutely wrong and I should never compose the repositories in UnitOfWork. Then please give me a solution about "Constructor Over-injection" here.
-- UPDATE2 --
It seems that composing (referencing to) the repositories from UnitOfWork breaks the Open/Closed principle as we need to change the UnitOfWork class when we add a new repository (add a new property).
If it's right then I should consider a refactoring. Would you please give me some ideas?
Upvotes: 3
Views: 385
Reputation: 233135
It seems as though the current design proposal mixes more than one responsibility into the IMyUnitOfWork interface. You say that this is because otherwise a service class might need to take each Repository independently. I'm assuming you mean something like this:
public MyService(
IUnitOfWork uow,
IFooRepository fooRepository,
IBarRepository barRepository)
This seems to me to be a much simpler and cleaner design.
But then what about Constructor Over-injection?
Well, there's that... but the thing is that this is exactly the same problem you now have with your ConcreteUnitOfWork implementation. You haven't solved the Constructor Over-injection smell at all - you've just moved it to another class.
Actually, by moving it to ConcreteUnitOfWork you've made it more difficult to deal with the situation. Because ConcreteUnitOfWork is a pure infrastructure class (or a support class, if you will) it doesn't have any business context, so it's really hard to suggest a way resolve the Constructor Over-injection smell here.
On the other hand, a given Service (or perhaps a Controller) would tend to be more specialized and have knowledge of the business context, so it wouldn't need every repository in order to do its job - or if it does, it probably attempts to do too much.
Such a specific business component can better be refactored to a Facade Service.
Upvotes: 5