Neardreams
Neardreams

Reputation: 125

How to simplify asp.net core dependency injection

Since asp.net core DI provides only constructor injection and method injection. If there's a lot of services to inject. Instead of writing a lot inside constructor and change constructors frequently. Can I just use some kind of provider so that I can get the services everywhere inside controller?

Instead of :

public class HomeController : BaseController
{
    public HomeController(
        IEmailService emailService,
        ISMSService smsService,
        ILogService logService,
        IProductRepository _productRepository)
        :base(emailService,smsService,logService)
    {
    }
    public IActionResult()
    {
        _emailService.SendSomething();
    }
    ...
}
public class BaseController : Controller
{
    protected readonly IEmailService _emailService;
    protected readonly ISMSService _smsService;
    protected readonly ILogService _logService;
    public BaseController(
        IEmailService emailService,
        ISMSService smsService,
        ILogService logService)
    {
        _emailService = emailService;
        _smsService = smsService;
        _logService = logService;
    }
}

With some kind of provider like:

public class HomeController : BaseController
{

    public HomeController(IDIServiceProvider provider)
        :base(provider)
    {

    }
    public IActionResult()
    {
        _provider.GetScopedService<IEmailService>().SendSomething();
    }
    ...
}
public class BaseController : Controller
{
    protected readonly IDIServiceProvider _provider;
    public BaseController(IDIServiceProvider provider)
    {
         _provider = provider;
    }
}

So that I don't have to change all controller's constructors every time when BaseController's constructor changes and simplify all controller's constructors.

Upvotes: 2

Views: 297

Answers (1)

Moien Tajik
Moien Tajik

Reputation: 2311

You can inject IServiceProvider to your controller and get your dependencies from that but it's not DI anymore and it's called Service Locator pattern.

public class HomeController
{
    private readonly ITestService _testService;

    public HomeController(IServiceProvider serviceProvider)
    {
        _testService = serviceProvider.GetRequiredService<ITestService>();
    }
}

It's recommended to not use Service Locator because :

1- Your controller dependencies are not obvious with the first look.

2- It's harder to write unit tests for that.

3- Your service now needs one more dependency (IServiceProvider).

Use Service Locator pattern only when it needed like injecting your dependencies to FilterAttributes or ValidationAttributes. ( You can use ServiceFilter for this situations too. )

Upvotes: 5

Related Questions