How to inject directly into your controller π’π€π΅πͺπ°π― methods in .π‘ππ§? π€ β Without using the constructor injection.
While the traditional constructor injection is widely used, another gem π in the DI toolbox is the [FromServices] attribute. It allows you to inject your service dependency directly into action methods without using the constructor approach.
It works seamlessly with the built-in DI container and provides a more concise and declarative way of handling dependencies within specific methods.
Pros and Cons
π Pros of [FromServices] attribute:
– Cleaner and more concise code without the constructor usage. β¨
– More control in certain scenarios where you may only require specific services for a particular action method.
– It’s an elegant solution when constructor injection is impossible, like with ActionFilters or ActionResults.
π However, there are also a few cons:
– Injected dependencies are a little more obscure compared to the constructor approach.
– It could be more difficult to inject services in a testing context. π§ͺ
The [FromServices] attribute presents an interesting alternative to constructor injection. Its concise nature and flexibility make it an attractive option for certain scenarios.
However, it’s essential to strike a balance between using [FromServices] and constructor injection to maintain code readability and testability.
In Practice
Let’s compare both, starting with the constructor injection:
public class CustomersController : Controller { private readonly ICustomerService _customerService; public CustomerController(ICustomerService customerService) { _customerService = customerService; } public IEnumerable<CustomerDto> GetCustomers() { // Sample code, no dto mapping return _customerService.GetCustomers(); } }
And now [FromServices] attribute:
public class CustomersController : Controller { public IEnumerable<CustomerDto> GetCustomers([FromServices] ICustomerService customerService) { // Sample code, no dto mapping return _customerService.GetCustomers(); } }
My Feedback
In practice, you could have too many dependencies injected into your constructor and want a lighter approach to inject only what you need using the [FromServices] attribute. It’s also probably a sign that you have to review your design and possibly have a more loose coupled solution with a better separation of concernsβ the Mediator pattern (MediatR) could be helpful in this case.
Finally, even if I don’t expect any noticeable gap, comparing performances with a benchmark could be interesting. My “by default” approach is still to inject dependencies through the constructor and switch to a more adapted design if the number of dependencies explodes.
Do you have any tips or π¦πΉπ±π¦π³πͺπ¦π―π€π¦π΄ with [ππΏπΌπΊπ¦π²πΏππΆπ°π²π] attribute?