diff --git a/src/Discord.Net.Commands/CommandService.cs b/src/Discord.Net.Commands/CommandService.cs index 7b7cffda2..5a092095f 100644 --- a/src/Discord.Net.Commands/CommandService.cs +++ b/src/Discord.Net.Commands/CommandService.cs @@ -1,3 +1,6 @@ +using Discord.Commands.Builders; +using Discord.Logging; +using Microsoft.Extensions.DependencyInjection; using System; using System.Collections.Concurrent; using System.Collections.Generic; @@ -350,8 +353,25 @@ namespace Discord.Commands => ExecuteAsync(context, context.Message.Content.Substring(argPos), services, multiMatchHandling); public async Task ExecuteAsync(ICommandContext context, string input, IServiceProvider services, MultiMatchHandling multiMatchHandling = MultiMatchHandling.Exception) { + // Create service scope and command context so dependent services can consume the command context, with a scoped lifespan services = services ?? EmptyServiceProvider.Instance; + using (var serviceScope = services.CreateScope()) + { + var scopedServices = serviceScope.ServiceProvider; + // If the context accessor is registered in the IoC container, set it + var contextAccessor = scopedServices.GetService(); + if (contextAccessor != null) + { + contextAccessor.CommandContext = context; + } + return await ExecuteAsyncInternal(context, input, scopedServices, multiMatchHandling); + } + } + + internal async Task ExecuteAsyncInternal(ICommandContext context, string input, + IServiceProvider services, MultiMatchHandling multiMatchHandling = MultiMatchHandling.Exception) + { var searchResult = Search(input); if (!searchResult.IsSuccess) return searchResult; diff --git a/src/Discord.Net.Core/Commands/CommandContextAccessor.cs b/src/Discord.Net.Core/Commands/CommandContextAccessor.cs new file mode 100644 index 000000000..1effb3707 --- /dev/null +++ b/src/Discord.Net.Core/Commands/CommandContextAccessor.cs @@ -0,0 +1,16 @@ +using System.Threading; + +namespace Discord.Commands +{ + public class CommandContextAccessor : ICommandContextAccessor + { + private static AsyncLocal _commandContextCurrent = new AsyncLocal(); + + public ICommandContext CommandContext + { + get => _commandContextCurrent.Value; + set => _commandContextCurrent.Value = value; + } + + } +} diff --git a/src/Discord.Net.Core/Commands/ICommandContextAccessor.cs b/src/Discord.Net.Core/Commands/ICommandContextAccessor.cs new file mode 100644 index 000000000..8a9e641fa --- /dev/null +++ b/src/Discord.Net.Core/Commands/ICommandContextAccessor.cs @@ -0,0 +1,7 @@ +namespace Discord.Commands +{ + public interface ICommandContextAccessor + { + ICommandContext CommandContext { get; set; } + } +}