Reputation: 69973
I hit a little road block trying to set up DI.
So given that I have this controller:
public UsersController(IUnitOfWork unitOfWork)
{
// Stuff
}
I previously had this UnitOfWork implementation that accessed my repositories directly.
public class UnitOfWork : IUnitOfWork, IDisposable
{
private readonly DbContext _context = new DbContext();
public IRepository<User> Users { get { return new UserRepository(_context); } }
}
Ninject UnitOfWork code: Bind<IUnitOfWork>().To<UnitOfWork>().InRequestScope();
Now this actually works fine. However I want to change it so that instead of UnitOfWork containing the repositories, it contains services which take in multiple repositories.
public class UserService : IUserService
{
private readonly IUserRepository _userRepository;
public UserService(IUserRepository userRepository, /* Other repositories */)
{
_userRepository = userRepository;
}
}
Right now the only solution I can come up with is
public class UnitOfWork : IUnitOfWork, IDisposable
{
private readonly DbContext _context = new DbContext();
public IUserService UserService
{
get
{
return new UserService(new UserRepository(_context), /* etc. */);
}
}
}
This doesn't seem right. Now I'm creating all of the service dependencies myself.
I've seen posts on StackOverflow mentioning that it's better to have services access the multiple repositories and handle the business logic rather than having the controller (MVC application) worry about it.
Can't find any specifics on how to actually do this properly though. So how could I use Ninject to do what I'm after?
Upvotes: 0
Views: 596
Reputation: 61795
Sorry, this is really an overgrown comment but hey...
A DbContext
is a Unit Of Work, and creating a monster unit of work that straddles two DbContexts is definitely not a general pattern (hence your question sez you)
The comments on this answer here to a related question stray into the same territory.
Questions to ask yourself before you try to solve it this way:
For me the crux is that creating your own UoW to wrap a UoW:
If you are still going to shoehorn this stuff in with Ninject in the way, the technical approach is to use the Context Preservation and Factory Extensions together - go read the examples in their wikis. If you decide to strip things back, they probably still have parts to play too.
UPDATE: I catch your drift now - it's important to link to stuff like that which is guiding your thinking up front. First, go read this. Next, decide if you're going to have a Unit of Work. If so, who and where is going to Commit and Dispose it?
If the Repositories and/or Services are going to share either a UoW or a DBContext and something is going to centrally Commit stuff, then you bind the things to be Shared/Disposed InRequestScope to have it a) get a single shared instance b) get Disposal
My main concern remains whether all these abstractions are all actually benefiting things - are you really writing tests that use the abstractions (and not just for the first few)? Are you really going to switch repositories. I personally would go read the DDD book a few times as a better time investment.
I realise a lot of this is highly patronising and this is just a simplified question representing part of a larger problem, but I've just seen too many questions recently prompted by the intersection of wrapping layers and DI container trickery hence my rant. Rant complete, thanks!
Upvotes: 2