RogerMKE
RogerMKE

Reputation: 737

UnitOfWork as a Container for Repositories

I have a solution that looks something like this:

Project1 <—> Shared Project <—> Project2

The Shared Project is not stand-alone, it exposes it's functionality to other projects through a service layer that accepts an IUnitOfWork that is injected into the constructor by each other other two projects:

public SharedService (IUnitOfWork unitOfWork)
{
   ... do stuff ...
}

The issue I am having is that Project1 and Project2 have an overlapping yet different set of repositories:

Project1: SharedRepository, RepositoryA, RepositoryB ...

Project2: SharedRepository, RepositoryX, RepositoryY ...

I keep seeing implementations of Unit Of Work where it is taking on the role of being a container for the repositories -- you pass around the UoW and then get to the repositories via public properties that expose them:

unitOfWork.SharedRepository.GetSomething();

The consequence of this approach is that you end up with a interface for your Unit of Work that looks like this:

public interface IUnitOfWork
{
    ISharedRepository SharedRepository();
    IRepositoryA RepositoryA();
    IRepositoryB RepositoryB();
    IRepositoryX RepositoryX();
    IRepositoryY RepositoryY();

    ... etc ...
}

Here is where I get in trouble: the interface IUnitOfWork is now forcing both Project1 and Project2 to implement each others repositories. So it appears to me that the approach of using Unit of Work as a container for repositories may be a flawed concept.

I have thought of some possible alternatives:

1) Break IUnitOfWork into 3 parts (IProject1UnitOfWork, IProject2UnitOfWork, ISharedUnitOfWork) and then have the service layer accept an ISharedUnitOfWork parameter. Seems messy, but it would probably work.

2) Turn UnitOfWork into something resembling a service locator, where it maintains a collection of repositories, and you register what you need. The consumer of the UoW then retrieves whatever repository it needs.

3) Have the Unit of Work and Repositories injected into the service layer constructors independently:

public SharedService (IUnitOfWork unitOfWork, ISharedRepository repository)
{
   ... do stuff ...
}

How would you guys handle a situation like this? I'm leaning towards option #3. It requires more things to be passed around, but the alternatives seem less elegant.

Upvotes: 2

Views: 240

Answers (1)

guillaume31
guillaume31

Reputation: 14064

So it appears to me that the approach of using Unit of Work as a container for repositories may be a flawed concept.

So does it to me. The Unit of Work in your example is also a pseudo-Service Locator (which is already generally considered an anti-pattern) and as such it violates SRP. UoW is just a transactional wrapper around whatever use case you want to place in it, it shouldn't know anything about repositories or any of the stuff that's in the use case.

See Dmitry's answer there : How does unit of work class know which repository to call on commit?

So, definitely option 3 for me.

Upvotes: 2

Related Questions