0

With-in ConfigureServices method, what is right way of retrieving object instance?

    public void ConfigureServices(IServiceCollection services)
    {
        services.AddScoped<SERVICES.Core.IAuthService, SERVICES.Core.AuthService>();
        //.......

        var serviceProvider = services.BuildServiceProvider();
        var authService = serviceProvider.GetRequiredService<IAuthService>();
    }

EDIT: Why?: Microsoft doesn't recommend us to use this. https://learn.microsoft.com/en-us/aspnet/core/fundamentals/dependency-injection?view=aspnetcore-5.0#ASP0000

Abhijeet
  • 13,562
  • 26
  • 94
  • 175
  • 1
    `serviceProvider.GetRequiredService();` – Chetan Jul 27 '21 at 15:22
  • `var authService = serviceProvider.GetService();` I use this in my project. – vsarunov Jul 27 '21 at 15:23
  • @vsarunov and @Chetan that's for `IServiceProvider` not `IServiceCollection`. – abdusco Jul 27 '21 at 15:26
  • 2
    And why you need it? It should be injected to the object which needs it – Selvin Jul 27 '21 at 15:28
  • Why would you wanna do this though? I have done it before and fix it to do proper injection – Lizo Matala Jul 27 '21 at 15:30
  • Depending on what you're using those services for (is it to select more services to register?) I would suggest using the overloads of Add...() that take `Func`. Then you can resolve services at the point the service is built and make decisions there just-in-time, rather than on the start-up path itself and build the container multiple times. – Martin Costello Jul 27 '21 at 15:33
  • @Selvin, I know its anti-pattern, on why I need this: https://stackoverflow.com/questions/68547805/what-is-alternative-of-addopenidconnect-middleware – Abhijeet Jul 27 '21 at 15:35

2 Answers2

2

If you need a service to register another, you can use a different overload to register it, where you have access to IServiceProvider:

services.AddScoped<IAnotherService>(
    provider =>
    {
        var authService = provider.GetRequiredService<IAuthService>();
        return new AnotherServiceImplementation(authService);
    }
);

If you need a service to configure something, you can implement an IConfigureOptions<MyOptions>.

services.AddSingleton<IConfigureOptions<MyOptions>, ConfigureMyOptions>();
class ConfigureMyOptions: IConfigureOptions<MyOptions>
{
    private IAuthService _authService; // inject a service
    private IConfiguration _configuration; // a configuration
    private SomeOptions _someOptions; // an option

    public ConfigureMyOptions(IAuthService authService, IConfiguration configuration, IOptions<SomeOptions> someOptions)
    {
        _authService = authService;
        _configuration = configuration;
        _someOptions = someOptions.Value;
    }

    public void Configure(MyOptions options)
    {
        // use _authService
        var something = _authService.GetSomething();
        _configuration.GetSection("MyOptions").Bind(options);
    }
}
abdusco
  • 9,700
  • 2
  • 27
  • 44
  • Thanks for sharing good overload, but the use-case is bit tricky than using the overload. https://stackoverflow.com/questions/68547805/what-is-alternative-of-addopenidconnect-middleware – Abhijeet Jul 27 '21 at 15:42
1

I use this in my project:

var authService = serviceProvider.GetService<SERVICES.Core.IAuthService>();

The difference between GetRequiredService<T> and GetService<T> Is that GetRequiredService<T> throws an exception if no service is found for the type T. While the GetService<T> returns null.

If you are ok to such a deal breaker use the first one, if you want to verify then you can use the second and check for null case. Depends on your case, I prefer the later in order to verify, though in most cases you would get a NullReferenceException.

vsarunov
  • 1,433
  • 14
  • 26