docs: Improved DI documentation (#2407)
This commit is contained in:
@@ -0,0 +1,9 @@
|
||||
async Task RunAsync()
|
||||
{
|
||||
//...
|
||||
|
||||
await _serviceProvider.GetRequiredService<ServiceActivator>()
|
||||
.ActivateAsync();
|
||||
|
||||
//...
|
||||
}
|
||||
13
docs/guides/dependency_injection/samples/collection.cs
Normal file
13
docs/guides/dependency_injection/samples/collection.cs
Normal file
@@ -0,0 +1,13 @@
|
||||
static IServiceProvider CreateServices()
|
||||
{
|
||||
var config = new DiscordSocketConfig()
|
||||
{
|
||||
//...
|
||||
};
|
||||
|
||||
var collection = new ServiceCollection()
|
||||
.AddSingleton(config)
|
||||
.AddSingleton<DiscordSocketClient>();
|
||||
|
||||
return collection.BuildServiceProvider();
|
||||
}
|
||||
14
docs/guides/dependency_injection/samples/ctor-injecting.cs
Normal file
14
docs/guides/dependency_injection/samples/ctor-injecting.cs
Normal file
@@ -0,0 +1,14 @@
|
||||
public class ClientHandler
|
||||
{
|
||||
private readonly DiscordSocketClient _client;
|
||||
|
||||
public ClientHandler(DiscordSocketClient client)
|
||||
{
|
||||
_client = client;
|
||||
}
|
||||
|
||||
public async Task ConfigureAsync()
|
||||
{
|
||||
//...
|
||||
}
|
||||
}
|
||||
18
docs/guides/dependency_injection/samples/enumeration.cs
Normal file
18
docs/guides/dependency_injection/samples/enumeration.cs
Normal file
@@ -0,0 +1,18 @@
|
||||
public class ServiceActivator
|
||||
{
|
||||
// This contains *all* registered services of serviceType IService
|
||||
private readonly IEnumerable<IService> _services;
|
||||
|
||||
public ServiceActivator(IEnumerable<IService> services)
|
||||
{
|
||||
_services = services;
|
||||
}
|
||||
|
||||
public async Task ActivateAsync()
|
||||
{
|
||||
foreach(var service in _services)
|
||||
{
|
||||
await service.StartAsync();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
16
docs/guides/dependency_injection/samples/modules.cs
Normal file
16
docs/guides/dependency_injection/samples/modules.cs
Normal file
@@ -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);
|
||||
}
|
||||
}
|
||||
24
docs/guides/dependency_injection/samples/program.cs
Normal file
24
docs/guides/dependency_injection/samples/program.cs
Normal file
@@ -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)
|
||||
{
|
||||
//...
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
public class ClientHandler
|
||||
{
|
||||
public DiscordSocketClient Client { get; set; }
|
||||
|
||||
public async Task ConfigureAsync()
|
||||
{
|
||||
//...
|
||||
}
|
||||
}
|
||||
26
docs/guides/dependency_injection/samples/provider.cs
Normal file
26
docs/guides/dependency_injection/samples/provider.cs
Normal file
@@ -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<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>();
|
||||
}
|
||||
}
|
||||
17
docs/guides/dependency_injection/samples/runasync.cs
Normal file
17
docs/guides/dependency_injection/samples/runasync.cs
Normal file
@@ -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<DiscordSocketClient>();
|
||||
|
||||
client.Log += async (msg) =>
|
||||
{
|
||||
await Task.CompletedTask;
|
||||
Console.WriteLine(msg);
|
||||
}
|
||||
|
||||
await client.LoginAsync(TokenType.Bot, "");
|
||||
await client.StartAsync();
|
||||
|
||||
await Task.Delay(Timeout.Infinite);
|
||||
}
|
||||
6
docs/guides/dependency_injection/samples/scoped.cs
Normal file
6
docs/guides/dependency_injection/samples/scoped.cs
Normal file
@@ -0,0 +1,6 @@
|
||||
|
||||
// With serviceType:
|
||||
collection.AddScoped<IScopedService, ScopedService>();
|
||||
|
||||
// Without serviceType:
|
||||
collection.AddScoped<ScopedService>();
|
||||
@@ -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<DiscordSocketClient>()
|
||||
.AddSingleton(servConfig)
|
||||
.AddSingleton<XService>();
|
||||
|
||||
return collection.BuildServiceProvider();
|
||||
}
|
||||
9
docs/guides/dependency_injection/samples/services.cs
Normal file
9
docs/guides/dependency_injection/samples/services.cs
Normal file
@@ -0,0 +1,9 @@
|
||||
public class MyService
|
||||
{
|
||||
public List<string> Things { get; }
|
||||
|
||||
public MyService()
|
||||
{
|
||||
Things = new();
|
||||
}
|
||||
}
|
||||
6
docs/guides/dependency_injection/samples/singleton.cs
Normal file
6
docs/guides/dependency_injection/samples/singleton.cs
Normal file
@@ -0,0 +1,6 @@
|
||||
|
||||
// With serviceType:
|
||||
collection.AddSingleton<ISingletonService, SingletonService>();
|
||||
|
||||
// Without serviceType:
|
||||
collection.AddSingleton<SingletonService>();
|
||||
6
docs/guides/dependency_injection/samples/transient.cs
Normal file
6
docs/guides/dependency_injection/samples/transient.cs
Normal file
@@ -0,0 +1,6 @@
|
||||
|
||||
// With serviceType:
|
||||
collection.AddTransient<ITransientService, TransientService>();
|
||||
|
||||
// Without serviceType:
|
||||
collection.AddTransient<TransientService>();
|
||||
Reference in New Issue
Block a user