This is a question about how best to do DI, so it’s not tied to any particular DI/IoC framework because, well, framework should be chosen based on pattern and practice rather than the other way around, no?
I’m doing a project where repository has to be injected into services, a service may require multiple repositories and I’m curious about the pros and cons between following approaches:
-
Inject repositories in service constructor
public class SomeService : ISomeService { private IRepository1 repository1; private IRepository2 repository2; public SomeService(IRepository1 repository1, IRepository2 repository2) { this.repository1 = repository1; this.repository2 = repository2; } public void DoThis() { //Do something with repository1 } public void DoThat() { //Do something with both repository1 and repository2 } } -
Inject a custom context class that include everything any service may need but lazy instantiated (the IServiceContext will be a protected field in BaseService)
public class SomeService : BaseService, ISomeService { public SomeService(IServiceContext serviceContext) { this.serviceContext= serviceContext; } public void DoThis() { //Do something with serviceContext.repository1 } public void DoThat() { //Do something with both serviceContext.repository1 and serviceContext.repository2 } } -
Inject into methods that need them only
public class SomeService : ISomeService { public void DoThis(IRepository1 repository1) { //Do something with repository1 } public void DoThat(IRepository1 repository1, IRepository2 repository2) { //Do something with both repository1 and repository2 } }
Some pointers would be appreciated, moreover what’re the aspects that I should consider in evaluating alternative like these?
The preferred way of injecting dependencies is Constructor Injection.
Method Injection is less ideal, because this will quickly result in having to pass around many dependencies from service to service and it will cause implementation details (the dependencies) to leak through the API (your method).
Both options 1 and 2 do Constructor Injection, which is good. If you find yourself having to inject too many dependencies in a constructor, there is something wrong. Either you are violating the Single Responsibility Principle, or you are missing some sort of aggregate service, and this is what you are doing in option 2.
In your case however, your
IServiceContextaggregate service is grouping multiple repositories together. Many repositories behind one class smells like a unit of work to me. Just add aCommitmethod to theIServiceContextand you will surely have a unit of work. Think about it: don’t you want to inject anIUnitOfWorkinto your service?