Is it good practice to pass service provider to our controller ?
Method No 1 :
[Authorize]
public abstract partial class BaseSecureController : Controller
{
private readonly IServiceProvider _serviceProvider;
protected readonly ISender _sender;
protected readonly Guid? _userId;
public BaseSecureController(IServiceProvider ServiceProvider)
{
_serviceProvider = ServiceProvider;
_sender = _serviceProvider.GetRequiredService<ISender>();
_userId = _serviceProvider.GetRequiredService<IUserContext>().UserId();
GeneralGuards.AgainstNullUserId(_userId);
}
}
In this approach we could add cached dictionary and then retrieve the services from it
Method No 2:
[Authorize]
public abstract partial class BaseSecureController : Controller
{
protected readonly ISender _sender;
protected readonly Guid? _userId;
public BaseSecureController(ISender sender, IUserContext userContext)
{
_sender = sender;
_userId = userContext?.UserId();
GeneralGuards.AgainstNullUserId(_userId);
}
}
In this approach, we will pass the injection from the controller that is inheriting this controller.
I want to know which approach is better with unit testing POV, good practice and performance wise in the long term.
IServiceProvider
contains all services, so as the number of services increases will it impact the performance of the first approach?
2 is the better approach.
Directly using IServiceProvider
is regarded as something of an anti-pattern. The code consuming the services is better when it does not know how it is provided with those services: better separation of concerns.
As the first comment on the question notes it also makes testing easier (less to double as a mock service provider is not needed).
IServiceProvider
contains all services, so as the number of services increases will it impact the performance of the first approach?
In the second approach the code that instantiates the controller gets the services needed to instantiate the controller from the service provider anyway, so the lookups into the provider will be the same. And framework code, as it is heavily used, gets a lot of performance attention that most business logic code cannot justify.