Table of Contents

Injecting instances within the provider

You can inject registered services into any class that is registered to the IServiceProvider. This can be done through property or constructor.

Note

As mentioned above, the dependency and the target class have to be registered in order for the serviceprovider to resolve it.

Injecting through a constructor

Services can be injected from the constructor of the class. This is the preferred approach, because it automatically locks the readonly field in place with the provided service and isn't accessible outside of the class.

public class ClientHandler
{
    private readonly DiscordSocketClient _client;

    public ClientHandler(DiscordSocketClient client)
    {
        _client = client;
    }

    public async Task ConfigureAsync()
    {
        //...
    }
}

Injecting through properties

Injecting through properties is also allowed as follows.

public class ClientHandler
{
    public DiscordSocketClient Client { get; set; }

    public async Task ConfigureAsync()
    {
        //...
    }
}
Warning

Dependency Injection will not resolve missing services in property injection, and it will not pick a constructor instead. If a publicly accessible property is attempted to be injected and its service is missing, the application will throw an error.

Using the provider itself

You can also access the provider reference itself from injecting it into a class. There are multiple use cases for this:

  • Allowing libraries (Like Discord.Net) to access your provider internally.
  • Injecting optional dependencies.
  • Calling methods on the provider itself if necessary, this is often done for creating scopes.
public class UtilizingProvider
{
    private readonly IServiceProvider _provider;
    private readonly AnyService _service;

    // This service is allowed to be null because it is only populated if the service is actually available in the provider.
    private readonly AnyOtherService? _otherService;

    // This constructor injects only the service provider,
    // and uses it to populate the other dependencies.
    public UtilizingProvider(IServiceProvider provider)
    {
        _provider = provider;
        _service = provider.GetRequiredService<AnyService>();
        _otherService = provider.GetService<AnyOtherService>();
    }

    // This constructor injects the service provider, and AnyService,
    // making sure that AnyService is not null without having to call GetRequiredService
    public UtilizingProvider(IServiceProvider provider, AnyService service)
    {
        _provider = provider;
        _service = service;
        _otherService = provider.GetService<AnyOtherService>();
    }
}
Note

It is important to keep in mind that the provider will pick the 'biggest' available constructor. If you choose to introduce multiple constructors, keep in mind that services missing from one constructor may have the provider pick another one that is available instead of throwing an exception.