DI in the Interaction- & Command Service
For both the Interaction- and Command Service modules, DI is quite straight-forward to use.
You can inject any service into modules without the modules having to be registered to the provider. Discord.Net resolves your dependencies internally.
Warning
The way DI is used in the Interaction- & Command Service are nearly identical, except for one detail: Resolving Module Dependencies
Registering the Service
Thanks to earlier described behavior of allowing already registered members as parameters of the available ctors, The socket client & configuration will automatically be acknowledged and the XService(client, config) overload will be used.
static IServiceProvider CreateServices()
{
var config = new DiscordSocketConfig()
{
//...
};
// X represents either Interaction or Command, as it functions the exact same for both types.
var servConfig = new XServiceConfig()
{
//...
}
var collection = new ServiceCollection()
.AddSingleton(config)
.AddSingleton<DiscordSocketClient>()
.AddSingleton(servConfig)
.AddSingleton<XService>();
return collection.BuildServiceProvider();
}
Usage in modules
In the constructor of your module, any parameters will be filled in by the IServiceProvider that you've passed.
Any publicly settable properties will also be filled in the same manner.
public class MyModule : InteractionModuleBase
{
private readonly MyService _service;
public MyModule(MyService service)
{
_service = service;
}
[SlashCommand("things", "Shows things")]
public async Task ThingsAsync()
{
var str = string.Join("\n", _service.Things)
await RespondAsync(str);
}
}
If you accept Command/InteractionService
or IServiceProvider
as a parameter in your constructor or as an injectable property,
these entries will be filled by the Command/InteractionService
that the module is loaded from and the IServiceProvider
that is passed into it respectively.
Note
Annotating a property with a [DontInjectAttribute] attribute will prevent the property from being injected.
Services
Because modules are transient of nature and will reinstantiate on every request, it is suggested to create a singleton service behind it to hold values across multiple command executions.
public class MyService
{
public List<string> Things { get; }
public MyService()
{
Things = new();
}
}