I am working on a service, which performs database operations through a repository. In the service I instantiate the repository which requires a database context in the constructor. I wanted to know if the context should be passed into the Service, or if the code below is fine. Or would it be better to pass a Repository object to the service for it to use? What should the UI code look like when using the Service class?
public class Service
{
private IRepository<WWW> _repository;
public Service()
{
_repository = new Repository<WWW>(new DBContext());
}
public WWW GetWWW(int wwwID)
{
return _repository.Get(x => x.WWWID == wwwID).FirstOrDefault();
}
public void AddWWW(WWW www)
{
_repository.Add(www);
}
public void DeleteWWWByID(int wwwID)
{
_repository.Delete(x => x.WWWID == wwwID);
}
public void SaveChanges()
{
_repository.SaveChanges();
}
}
Indeed, it would be better to pass a repository to the Service via the Service’s constructor, like so:
Tipically, the class representing the UI would take a dependency on Service, so the code might look like this:
What you have to do next is configure an Inversion of Control container that will know how to resolve instances of IRepository (and feeding them appropriate DataContext instance, if needed).
For example, if our UI code would be an MVC3 controller, we’d tell the container to resolve an instance of this controller. This is what happens:
The container notices the dependency on
Service(in the constructor) and tries to resolve it.Since
Serviceis a concrete class, the container will attempt to resolve it and thennotice the dependency on
IRepository<WWW>.The resolution of
IRepository, since this is an interface, requires that the container has been previously set up to “know” what to return when it’s asked for an instance of it. Normally, this is just a mapping between the interface and a concrete implementation of it. In our case the concrete implementation isRepository<WWW>and the container is also responsible for “knowing” how to instantiate the neededDataContextinstance for it (this also has to be previously configured)Having a repository instance, the container is then able to properly instantiate first the
Service, then the controller class.Note that the automatic resolution of concrete classes is a feature not all IoC containers have; some require explicit configuration in order to do so.
Apart from this, I think the
Serviceclass does not add much value in your case. It only contains delegations to methods implemented by the repository. In this case it could be better to have the UI take a dependency on theIRepository<WWW>directly and simply delete theServiceclass.However, if this
Serviceclass was just an example and in your real project it implements actual business rules, then it should be kept.Update: How to resolve dependencies in ASP.Net Webforms
The example I presented above is the ideal Dependency Injection scenario. It would work for example in ASP.NET MVC, where BaseClassDictatedByCurrentUIFramework would be
Controller– in that case the framework allows us to control the components that instantiate Controllers, so we can inject our own dependencies in the constructor.However, ASP.Net WebForms is not a very DI-friendly framework. It requires that every
Pageis required to have a default constructor, which makes all the constructor injection idea not suitable.In this case one possible solution would be the following compromise:
Pageclass declare dependencies asprivate readonlyfields, but the constructor will not have corresponding parameters (it will have no parameters at all)Please note that this approach requires discipline – it is easy to use the container somewhere else that the constructor to resolve other components. This approach is called Service Locator, it’s considered an antipattern (http://blog.ploeh.dk/2010/02/03/ServiceLocatorIsAnAntiPattern.aspx) and should therefore be avoided.