Skip to content

Dependency Injection

GreemDev edited this page Aug 9, 2019 · 3 revisions

Dependency Injection is a core part of Volte. It handles instantiation of Volte's Services automatically and passes around a single instance for reuse, reducing static abuse.

Volte already has an IServiceProvider. To add a Service into Volte's ServiceProvider, you should use the VolteService or VolteEventService base class. VolteEventService has a forced-overridable method, DoAsync(EventArgs), this is to allow basic polymorphism. VolteService is used for services that do not act on one single event; like the WelcomeService or DatabaseService.

Example:

public sealed class MusicService : VolteService {}

or

public sealed class ThisHandlesSomeGatewayEventService : VolteEventService 
{
    public async Task DoAsync(EventArgs args)
        => await SomeEventAsync(args.Cast<SomeVolteEventArgClass>()); //cast event args as the base class just uses the System.EventArgs base type
                                                                      //object#Cast<T>() is a Gommon object extension method

    private async Task SomeEventAsync(SomeVolteEventArgClass args) {} //actual logic here

}

Services can be under any namespace (however if you're PR'ing then you should put it under Volte.Services), as the extension method for adding Services via reflection just checks if the type has the attribute and ignores namespace.

Injecting into a Service

To have Services handled by DI injected into your service, you need to add them as fields and a constructor. Example:

private readonly LoggingService _logger;

public AutoroleService(LoggingService loggingService) 
{
    _logger = loggingService;
}

This will, upon creation of AutoroleService, inject the _logger property, using the shared instance of LoggingService as opposed to just new LoggingService().

Injecting into a Command

A public, publicly-settable property will suffice. If you, for example, needed the ModLogService in a Command class, you'd do the following:

public partial class UtilityModule : VolteModule 
{
    public ModLogService ModLogService { get; set; }

    //ooga booga command stuff

}

Once you do that, you can use the shared instance of ModLogService in your command. You can also do constructor injection in commands, but you can NOT do property injection in Services; and you're forced to do constructor injection as shown above.

Clone this wiki locally