diff --git a/docs/guides/dependency_injection/basics.md b/docs/guides/dependency_injection/basics.md new file mode 100644 index 000000000..c553ee68c --- /dev/null +++ b/docs/guides/dependency_injection/basics.md @@ -0,0 +1,69 @@ +--- +uid: Guides.DI.Intro +title: Introduction +--- + +# Dependency Injection + +Dependency injection is a feature not required in Discord.Net, but makes it a lot easier to use. +It can be combined with a large number of other libraries, and gives you better control over your application. + +> Further into the documentation, Dependency Injection will be referred to as 'DI'. + +## Installation + +DI is not native to .NET. You need to install the extension packages to your project in order to use it: + +- [Meta](https://www.nuget.org/packages/Microsoft.Extensions.DependencyInjection/). +- [Abstractions](https://www.nuget.org/packages/Microsoft.Extensions.DependencyInjection.Abstractions/). + +> [!WARNING] +> Downloading the abstractions package alone will not give you access to required classes to use DI properly. +> Please install both packages, or choose to only install the meta package to implicitly install both. + +### Visual Package Manager: + +[Installing](images/manager.png) + +### Command Line: + +`PM> Install-Package Microsoft.Extensions.DependencyInjection`. + +> [!TIP] +> ASP.NET already comes packed with all the necessary assemblies in its framework. +> You do not require to install any additional NuGet packages to make full use of all features of DI in ASP.NET projects. + +## Getting started + +First of all, you will need to create an application based around dependency injection, +which in order will be able to access and inject them across the project. + +[!code-csharp[Building the Program](samples/program.cs)] + +In order to freely pass around your dependencies in different classes, +you will need to register them to a new `ServiceCollection` and build them into an `IServiceProvider` as seen above. +The IServiceProvider then needs to be accessible by the startup file, so you can access your provider and manage them. + +[!code-csharp[Building the Collection](samples/collection.cs)] + +As shown above, an instance of `DiscordSocketConfig` is created, and added **before** the client itself is. +Because the collection will prefer to create the highest populated constructor available with the services already present, +it will prefer the constructor with the configuration, because you already added it. + +## Using your dependencies + +After building your provider in the Program class constructor, the provider is now available inside the instance you're actively using. +Through the provider, we can ask for the DiscordSocketClient we registered earlier. + +[!code-csharp[Applying DI in RunAsync](samples/runasync.cs)] + +> [!WARNING] +> Service constructors are not activated until the service is **first requested**. +> An 'endpoint' service will have to be requested from the provider before it is activated. +> If a service is requested with dependencies, its dependencies (if not already active) will be activated before the service itself is. + +## Injecting dependencies + +You can not only directly access the provider from a field or property, but you can also pass around instances to classes registered in the provider. +There are multiple ways to do this. Please refer to the +[Injection Documentation](Guides.DI.Injection) for further information. diff --git a/docs/guides/dependency_injection/images/manager.png b/docs/guides/dependency_injection/images/manager.png new file mode 100644 index 000000000..91791f7a0 Binary files /dev/null and b/docs/guides/dependency_injection/images/manager.png differ diff --git a/docs/guides/dependency_injection/injection.md b/docs/guides/dependency_injection/injection.md new file mode 100644 index 000000000..c7d40c479 --- /dev/null +++ b/docs/guides/dependency_injection/injection.md @@ -0,0 +1,44 @@ +--- +uid: Guides.DI.Injection +title: Injection +--- + +# 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. + +[!code-csharp[Property Injection(samples/property-injecting.cs)]] + +## Injecting through properties + +Injecting through properties is also allowed as follows. + +[!code-csharp[Property Injection](samples/property-injecting.cs)] + +> [!WARNING] +> Dependency Injection will not resolve missing services in property injection, and it will not pick a constructor instead. +> If a publically 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. + +[!code-csharp[Provider Injection](samples/provider.cs)] + +> [!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. diff --git a/docs/guides/dependency_injection/samples/access-activator.cs b/docs/guides/dependency_injection/samples/access-activator.cs new file mode 100644 index 000000000..29e71e894 --- /dev/null +++ b/docs/guides/dependency_injection/samples/access-activator.cs @@ -0,0 +1,9 @@ +async Task RunAsync() +{ + //... + + await _serviceProvider.GetRequiredService() + .ActivateAsync(); + + //... +} diff --git a/docs/guides/dependency_injection/samples/collection.cs b/docs/guides/dependency_injection/samples/collection.cs new file mode 100644 index 000000000..4d0457dc9 --- /dev/null +++ b/docs/guides/dependency_injection/samples/collection.cs @@ -0,0 +1,13 @@ +static IServiceProvider CreateServices() +{ + var config = new DiscordSocketConfig() + { + //... + }; + + var collection = new ServiceCollection() + .AddSingleton(config) + .AddSingleton(); + + return collection.BuildServiceProvider(); +} diff --git a/docs/guides/dependency_injection/samples/ctor-injecting.cs b/docs/guides/dependency_injection/samples/ctor-injecting.cs new file mode 100644 index 000000000..c412bd29c --- /dev/null +++ b/docs/guides/dependency_injection/samples/ctor-injecting.cs @@ -0,0 +1,14 @@ +public class ClientHandler +{ + private readonly DiscordSocketClient _client; + + public ClientHandler(DiscordSocketClient client) + { + _client = client; + } + + public async Task ConfigureAsync() + { + //... + } +} diff --git a/docs/guides/dependency_injection/samples/enumeration.cs b/docs/guides/dependency_injection/samples/enumeration.cs new file mode 100644 index 000000000..cc8c617f3 --- /dev/null +++ b/docs/guides/dependency_injection/samples/enumeration.cs @@ -0,0 +1,18 @@ +public class ServiceActivator +{ + // This contains *all* registered services of serviceType IService + private readonly IEnumerable _services; + + public ServiceActivator(IEnumerable services) + { + _services = services; + } + + public async Task ActivateAsync() + { + foreach(var service in _services) + { + await service.StartAsync(); + } + } +} diff --git a/docs/guides/dependency_injection/samples/implicit-registration.cs b/docs/guides/dependency_injection/samples/implicit-registration.cs new file mode 100644 index 000000000..52f84228b --- /dev/null +++ b/docs/guides/dependency_injection/samples/implicit-registration.cs @@ -0,0 +1,12 @@ +public static ServiceCollection RegisterImplicitServices(this ServiceCollection collection, Type interfaceType, Type activatorType) +{ + // Get all types in the executing assembly. There are many ways to do this, but this is fastest. + foreach (var type in typeof(Program).Assembly.GetTypes()) + { + if (interfaceType.IsAssignableFrom(type) && !type.IsAbstract) + collection.AddSingleton(interfaceType, type); + } + + // Register the activator so you can activate the instances. + collection.AddSingleton(activatorType); +} diff --git a/docs/guides/dependency_injection/samples/modules.cs b/docs/guides/dependency_injection/samples/modules.cs new file mode 100644 index 000000000..2fadc13d4 --- /dev/null +++ b/docs/guides/dependency_injection/samples/modules.cs @@ -0,0 +1,16 @@ +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); + } +} diff --git a/docs/guides/dependency_injection/samples/program.cs b/docs/guides/dependency_injection/samples/program.cs new file mode 100644 index 000000000..6d985319a --- /dev/null +++ b/docs/guides/dependency_injection/samples/program.cs @@ -0,0 +1,24 @@ +public class Program +{ + private readonly IServiceProvider _serviceProvider; + + public Program() + { + _serviceProvider = CreateProvider(); + } + + static void Main(string[] args) + => new Program().RunAsync(args).GetAwaiter().GetResult(); + + static IServiceProvider CreateProvider() + { + var collection = new ServiceCollection(); + //... + return collection.BuildServiceProvider(); + } + + async Task RunAsync(string[] args) + { + //... + } +} diff --git a/docs/guides/dependency_injection/samples/property-injecting.cs b/docs/guides/dependency_injection/samples/property-injecting.cs new file mode 100644 index 000000000..c0c50e150 --- /dev/null +++ b/docs/guides/dependency_injection/samples/property-injecting.cs @@ -0,0 +1,9 @@ +public class ClientHandler +{ + public DiscordSocketClient Client { get; set; } + + public async Task ConfigureAsync() + { + //... + } +} diff --git a/docs/guides/dependency_injection/samples/provider.cs b/docs/guides/dependency_injection/samples/provider.cs new file mode 100644 index 000000000..26b600b9d --- /dev/null +++ b/docs/guides/dependency_injection/samples/provider.cs @@ -0,0 +1,26 @@ +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(); + _otherService = provider.GetService(); + } + + // 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(); + } +} diff --git a/docs/guides/dependency_injection/samples/runasync.cs b/docs/guides/dependency_injection/samples/runasync.cs new file mode 100644 index 000000000..d24efc83e --- /dev/null +++ b/docs/guides/dependency_injection/samples/runasync.cs @@ -0,0 +1,17 @@ +async Task RunAsync(string[] args) +{ + // Request the instance from the client. + // Because we're requesting it here first, its targetted constructor will be called and we will receive an active instance. + var client = _services.GetRequiredService(); + + client.Log += async (msg) => + { + await Task.CompletedTask; + Console.WriteLine(msg); + } + + await client.LoginAsync(TokenType.Bot, ""); + await client.StartAsync(); + + await Task.Delay(Timeout.Infinite); +} diff --git a/docs/guides/dependency_injection/samples/scoped.cs b/docs/guides/dependency_injection/samples/scoped.cs new file mode 100644 index 000000000..9942f8d8e --- /dev/null +++ b/docs/guides/dependency_injection/samples/scoped.cs @@ -0,0 +1,6 @@ + +// With serviceType: +collection.AddScoped(); + +// Without serviceType: +collection.AddScoped(); diff --git a/docs/guides/dependency_injection/samples/service-registration.cs b/docs/guides/dependency_injection/samples/service-registration.cs new file mode 100644 index 000000000..f6e4d22dd --- /dev/null +++ b/docs/guides/dependency_injection/samples/service-registration.cs @@ -0,0 +1,21 @@ +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() + .AddSingleton(servConfig) + .AddSingleton(); + + return collection.BuildServiceProvider(); +} diff --git a/docs/guides/dependency_injection/samples/services.cs b/docs/guides/dependency_injection/samples/services.cs new file mode 100644 index 000000000..2e5235b69 --- /dev/null +++ b/docs/guides/dependency_injection/samples/services.cs @@ -0,0 +1,9 @@ +public class MyService +{ + public List Things { get; } + + public MyService() + { + Things = new(); + } +} diff --git a/docs/guides/dependency_injection/samples/singleton.cs b/docs/guides/dependency_injection/samples/singleton.cs new file mode 100644 index 000000000..f395d743e --- /dev/null +++ b/docs/guides/dependency_injection/samples/singleton.cs @@ -0,0 +1,6 @@ + +// With serviceType: +collection.AddSingleton(); + +// Without serviceType: +collection.AddSingleton(); diff --git a/docs/guides/dependency_injection/samples/transient.cs b/docs/guides/dependency_injection/samples/transient.cs new file mode 100644 index 000000000..ae1e1a5d8 --- /dev/null +++ b/docs/guides/dependency_injection/samples/transient.cs @@ -0,0 +1,6 @@ + +// With serviceType: +collection.AddTransient(); + +// Without serviceType: +collection.AddTransient(); diff --git a/docs/guides/dependency_injection/scaling.md b/docs/guides/dependency_injection/scaling.md new file mode 100644 index 000000000..356fb7c72 --- /dev/null +++ b/docs/guides/dependency_injection/scaling.md @@ -0,0 +1,39 @@ +--- +uid: Guides.DI.Scaling +title: Scaling your DI +--- + +# Scaling your DI + +Dependency injection has a lot of use cases, and is very suitable for scaled applications. +There are a few ways to make registering & using services easier in large amounts. + +## Using a range of services. + +If you have a lot of services that all have the same use such as handling an event or serving a module, +you can register and inject them all at once by some requirements: + +- All classes need to inherit a single interface or abstract type. +- While not required, it is preferred if the interface and types share a method to call on request. +- You need to register a class that all the types can be injected into. + +### Registering implicitly + +Registering all the types is done through getting all types in the assembly and checking if they inherit the target interface. + +[!code-csharp[Registering](samples/implicit-registration.cs)] + +> [!NOTE] +> As seen above, the interfaceType and activatorType are undefined. For our usecase below, these are `IService` and `ServiceActivator` in order. + +### Using implicit dependencies + +In order to use the implicit dependencies, you have to get access to the activator you registered earlier. + +[!code-csharp[Accessing the activator](samples/access-activator.cs)] + +When the activator is accessed and the `ActivateAsync()` method is called, the following code will be executed: + +[!code-csharp[Executing the activator](samples/enumeration.cs)] + +As a result of this, all the services that were registered with `IService` as its implementation type will execute their starting code, and start up. diff --git a/docs/guides/dependency_injection/services.md b/docs/guides/dependency_injection/services.md new file mode 100644 index 000000000..e021a88be --- /dev/null +++ b/docs/guides/dependency_injection/services.md @@ -0,0 +1,48 @@ +--- +uid: Guides.DI.Services +title: Using DI in Interaction & Command Frameworks +--- + +# 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](xref:Guides.IntFw.Intro#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. + +[!code-csharp[Service Registration](samples/service-registration.cs)] + +## Usage in modules + +In the constructor of your module, any parameters will be filled in by +the @System.IServiceProvider that you've passed. + +Any publicly settable properties will also be filled in the same +manner. + +[!code-csharp[Module Injection](samples/modules.cs)] + +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. + +[!code-csharp[Services](samples/services.cs)] + + diff --git a/docs/guides/dependency_injection/types.md b/docs/guides/dependency_injection/types.md new file mode 100644 index 000000000..e539d0695 --- /dev/null +++ b/docs/guides/dependency_injection/types.md @@ -0,0 +1,52 @@ +--- +uid: Guides.DI.Dependencies +title: Types of Dependencies +--- + +# Dependency Types + +There are 3 types of dependencies to learn to use. Several different usecases apply for each. + +> [!WARNING] +> When registering types with a serviceType & implementationType, +> only the serviceType will be available for injection, and the implementationType will be used for the underlying instance. + +## Singleton + +A singleton service creates a single instance when first requested, and maintains that instance across the lifetime of the application. +Any values that are changed within a singleton will be changed across all instances that depend on it, as they all have the same reference to it. + +### Registration: + +[!code-csharp[Singleton Example](samples/singleton.cs)] + +> [!NOTE] +> Types like the Discord client and Interaction/Command services are intended to be singleton, +> as they should last across the entire app and share their state with all references to the object. + +## Scoped + +A scoped service creates a new instance every time a new service is requested, but is kept across the 'scope'. +As long as the service is in view for the created scope, the same instance is used for all references to the type. +This means that you can reuse the same instance during execution, and keep the services' state for as long as the request is active. + +### Registration: + +[!code-csharp[Scoped Example](samples/scoped.cs)] + +> [!NOTE] +> Without using HTTP or libraries like EFCORE, scopes are often unused in Discord bots. +> They are most commonly used for handling HTTP and database requests. + +## Transient + +A transient service is created every time it is requested, and does not share its state between references within the target service. +It is intended for lightweight types that require little state, to be disposed quickly after execution. + +### Registration: + +[!code-csharp[Transient Example](samples/transient.cs)] + +> [!NOTE] +> Discord.Net modules behave exactly as transient types, and are intended to only last as long as the command execution takes. +> This is why it is suggested for apps to use singleton services to keep track of cross-execution data. diff --git a/docs/guides/int_framework/dependency-injection.md b/docs/guides/int_framework/dependency-injection.md deleted file mode 100644 index 31d001f4b..000000000 --- a/docs/guides/int_framework/dependency-injection.md +++ /dev/null @@ -1,13 +0,0 @@ ---- -uid: Guides.IntFw.DI -title: Dependency Injection ---- - -# Dependency Injection - -Dependency injection in the Interaction Service is mostly based on that of the Text-based command service, -for which further information is found [here](xref:Guides.TextCommands.DI). - -> [!NOTE] -> The 2 are nearly identical, except for one detail: -> [Resolving Module Dependencies](xref:Guides.IntFw.Intro#resolving-module-dependencies) diff --git a/docs/guides/int_framework/intro.md b/docs/guides/int_framework/intro.md index b51aa8088..5cf38bff1 100644 --- a/docs/guides/int_framework/intro.md +++ b/docs/guides/int_framework/intro.md @@ -374,8 +374,7 @@ delegate can be used to create HTTP responses from a deserialized json object st - Use the interaction endpoints of the module base instead of the interaction object (ie. `RespondAsync()`, `FollowupAsync()`...). [AutocompleteHandlers]: xref:Guides.IntFw.AutoCompletion -[DependencyInjection]: xref:Guides.TextCommands.DI -[Post Execution Docuemntation]: xref:Guides.IntFw.PostExecution +[DependencyInjection]: xref:Guides.DI.Intro [GroupAttribute]: xref:Discord.Interactions.GroupAttribute [InteractionService]: xref:Discord.Interactions.InteractionService diff --git a/docs/guides/text_commands/dependency-injection.md b/docs/guides/text_commands/dependency-injection.md deleted file mode 100644 index 3253643ef..000000000 --- a/docs/guides/text_commands/dependency-injection.md +++ /dev/null @@ -1,51 +0,0 @@ ---- -uid: Guides.TextCommands.DI -title: Dependency Injection ---- - -# Dependency Injection - -The Text Command Service is bundled with a very barebone Dependency -Injection service for your convenience. It is recommended that you use -DI when writing your modules. - -> [!WARNING] -> If you were brought here from the Interaction Service guides, -> make sure to replace all namespaces that imply `Discord.Commands` with `Discord.Interactions` - -## Setup - -1. Create a @Microsoft.Extensions.DependencyInjection.ServiceCollection. -2. Add the dependencies to the service collection that you wish - to use in the modules. -3. Build the service collection into a service provider. -4. Pass the service collection into @Discord.Commands.CommandService.AddModulesAsync* / @Discord.Commands.CommandService.AddModuleAsync* , @Discord.Commands.CommandService.ExecuteAsync* . - -### Example - Setting up Injection - -[!code-csharp[IServiceProvider Setup](samples/dependency-injection/dependency_map_setup.cs)] - -## Usage in Modules - -In the constructor of your module, any parameters will be filled in by -the @System.IServiceProvider that you've passed. - -Any publicly settable properties will also be filled in the same -manner. - -> [!NOTE] -> Annotating a property with a [DontInjectAttribute] attribute will -> prevent the property from being injected. - -> [!NOTE] -> If you accept `CommandService` or `IServiceProvider` as a parameter -> in your constructor or as an injectable property, these entries will -> be filled by the `CommandService` that the module is loaded from and -> the `IServiceProvider` that is passed into it respectively. - -### Example - Injection in Modules - -[!code-csharp[Injection Modules](samples/dependency-injection/dependency_module.cs)] -[!code-csharp[Disallow Dependency Injection](samples/dependency-injection/dependency_module_noinject.cs)] - -[DontInjectAttribute]: xref:Discord.Commands.DontInjectAttribute diff --git a/docs/guides/text_commands/intro.md b/docs/guides/text_commands/intro.md index 6632c127a..1113b0821 100644 --- a/docs/guides/text_commands/intro.md +++ b/docs/guides/text_commands/intro.md @@ -187,7 +187,7 @@ service provider. ### Module Constructors -Modules are constructed using [Dependency Injection](xref:Guides.TextCommands.DI). Any parameters +Modules are constructed using [Dependency Injection](xref:Guides.DI.Intro). Any parameters that are placed in the Module's constructor must be injected into an @System.IServiceProvider first. diff --git a/docs/guides/text_commands/samples/dependency-injection/dependency_map_setup.cs b/docs/guides/text_commands/samples/dependency-injection/dependency_map_setup.cs deleted file mode 100644 index 16ca479db..000000000 --- a/docs/guides/text_commands/samples/dependency-injection/dependency_map_setup.cs +++ /dev/null @@ -1,65 +0,0 @@ -public class Initialize -{ - private readonly CommandService _commands; - private readonly DiscordSocketClient _client; - - // Ask if there are existing CommandService and DiscordSocketClient - // instance. If there are, we retrieve them and add them to the - // DI container; if not, we create our own. - public Initialize(CommandService commands = null, DiscordSocketClient client = null) - { - _commands = commands ?? new CommandService(); - _client = client ?? new DiscordSocketClient(); - } - - public IServiceProvider BuildServiceProvider() => new ServiceCollection() - .AddSingleton(_client) - .AddSingleton(_commands) - // You can pass in an instance of the desired type - .AddSingleton(new NotificationService()) - // ...or by using the generic method. - // - // The benefit of using the generic method is that - // ASP.NET DI will attempt to inject the required - // dependencies that are specified under the constructor - // for us. - .AddSingleton() - .AddSingleton() - .BuildServiceProvider(); -} -public class CommandHandler -{ - private readonly DiscordSocketClient _client; - private readonly CommandService _commands; - private readonly IServiceProvider _services; - - public CommandHandler(IServiceProvider services, CommandService commands, DiscordSocketClient client) - { - _commands = commands; - _services = services; - _client = client; - } - - public async Task InitializeAsync() - { - // Pass the service provider to the second parameter of - // AddModulesAsync to inject dependencies to all modules - // that may require them. - await _commands.AddModulesAsync( - assembly: Assembly.GetEntryAssembly(), - services: _services); - _client.MessageReceived += HandleCommandAsync; - } - - public async Task HandleCommandAsync(SocketMessage msg) - { - // ... - // Pass the service provider to the ExecuteAsync method for - // precondition checks. - await _commands.ExecuteAsync( - context: context, - argPos: argPos, - services: _services); - // ... - } -} diff --git a/docs/guides/text_commands/samples/dependency-injection/dependency_module.cs b/docs/guides/text_commands/samples/dependency-injection/dependency_module.cs deleted file mode 100644 index 3e42074ca..000000000 --- a/docs/guides/text_commands/samples/dependency-injection/dependency_module.cs +++ /dev/null @@ -1,37 +0,0 @@ -// After setting up dependency injection, modules will need to request -// the dependencies to let the library know to pass -// them along during execution. - -// Dependency can be injected in two ways with Discord.Net. -// You may inject any required dependencies via... -// the module constructor -// -or- -// public settable properties - -// Injection via constructor -public class DatabaseModule : ModuleBase -{ - private readonly DatabaseService _database; - public DatabaseModule(DatabaseService database) - { - _database = database; - } - - [Command("read")] - public async Task ReadFromDbAsync() - { - await ReplyAsync(_database.GetData()); - } -} - -// Injection via public settable properties -public class DatabaseModule : ModuleBase -{ - public DatabaseService DbService { get; set; } - - [Command("read")] - public async Task ReadFromDbAsync() - { - await ReplyAsync(DbService.GetData()); - } -} diff --git a/docs/guides/text_commands/samples/dependency-injection/dependency_module_noinject.cs b/docs/guides/text_commands/samples/dependency-injection/dependency_module_noinject.cs deleted file mode 100644 index 48cd52308..000000000 --- a/docs/guides/text_commands/samples/dependency-injection/dependency_module_noinject.cs +++ /dev/null @@ -1,29 +0,0 @@ -// Sometimes injecting dependencies automatically with the provided -// methods in the prior example may not be desired. - -// You may explicitly tell Discord.Net to **not** inject the properties -// by either... -// restricting the access modifier -// -or- -// applying DontInjectAttribute to the property - -// Restricting the access modifier of the property -public class ImageModule : ModuleBase -{ - public ImageService ImageService { get; } - public ImageModule() - { - ImageService = new ImageService(); - } -} - -// Applying DontInjectAttribute -public class ImageModule : ModuleBase -{ - [DontInject] - public ImageService ImageService { get; set; } - public ImageModule() - { - ImageService = new ImageService(); - } -}