Mekswoll
Mekswoll

Reputation: 1433

EF4.3 dependency injection when creating new objects yourself

I'm building an MVC3 application using the Entity Framework. In the application my controllers talk to a service layer. One of the controllers is a TournamentController which uses the TournamentService. This service has some standard methods such as CreateTournament, UpdateTournament etc.

When I want to insert a new tournament I want the view to have a dropdownlist of possible sports for which the tournament can be organised. So in the TournamentController's Create method I fill the ViewBag.Sports with a list of possible sports. Now to obtain this list of sports I use _tournamentService.GetAllSports(). In this GetAllSports() method of the TournamentService I want to create an instance of the SportService so I can 'forward' the question to the right service.

All services use dependency injection in the constructor to inject their own repository, like so:

private ITournamentRepository _repo;

public TournamentService(ITournamentRepository repo) {
    _repo = repo;
}

My GetAllSports() method in the TournamentService looks like this:

public IEnumerable<Sport> GetAllSports() {
    ISportService sportService = new SportService();
    return sportService.GetSports();
}

The problem is that by calling the new SportService() it expects me to hand it an ISportRepository like in the TournamentService, where ninject creates the TournamentRepository. Now I could do the following:

public IEnumerable<Sport> GetAllSports() {
    ISportService sportService = new SportService(new SportRepository());
    return sportService.GetSports();
}

But the problem with that is that each repository expects an IContext, which is normally handled by ninject as well. Furthermore, I don't want two separate contexts to be instantiated.

A possible solution I found myself is to do this:

private ITournamentRepository _repo;
private ISportService _sportService;

public TournamentService(ITournamentRepository repo, ISportService sportService) {
    _repo = repo;
    _sportService = sportService
}

But there's only one method in my TournamentService class that would actually use the _sportService so I figure this is a bit overkill to make it a class attribute.

Upvotes: 0

Views: 180

Answers (2)

Khepri
Khepri

Reputation: 9627

Your last solution valid. Inject the necessary service as part of the constructor.

And if you're worried about multiple contexts, don't let two separate contexts be created then.

In your Ninject binding:

Bind<ITournamentRepository>().To<TournamentRepository>().InRequestScope();

See https://github.com/ninject/Ninject.Web.Common/wiki/InRequestScope

The last piece is the important part. It will only create one instance of TournamentRepository for the current request. Any other requesters of TournamentRepository will get this instance.

If you're already doing this, you're set, otherwise, just add InRequestScope and you're done. (keeping in mind you'll need a reference to Ninject.Web.Common)

Hope that helps.

EDIT:

Remo is correct, I wouldn't call this from a service either. Just call for your lookup data from the controller and populate your view model. The InRequestScope advice still holds.

Upvotes: 1

Remo Gloor
Remo Gloor

Reputation: 32725

Keep it simple, inject ISportService to your controller and call sportService.GetSports() directly from the controller!

Upvotes: 1

Related Questions