Dependency Injection
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
base class. Upon startup, the current Assembly's types are filtered on whether or not they inherit the base class VolteService
; all of the remaining types from this filter are then added to the ServiceProvider
.
Example:
public sealed class MusicService : VolteService {}
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 is VolteService
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 assigning its value.
Example Implementation
public sealed class MusicService : VolteService {
private readonly LoggingService _logger;
public MusicService(LoggingService loggingService)
{
_logger = loggingService;
}
}
This will, upon creation of MusicService
, inject the _logger
property, using the shared instance of LoggingService
as opposed to just new LoggingService()
; allowing you to use shared resources, such as a database instance or some sort of necessary persistent data.
Injecting into a Command
A public, publicly-settable property will suffice.
If you, for example, needed the ModerationService
in a Command class, you'd do the following:
public partial class UtilityModule : VolteModule
{
public ModLogService ModLogService { get; set; }
//ooga booga command stuff
}
ModerationService
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 as the property behavior is exclusive to the command library used.