| @@ -114,7 +114,7 @@ namespace Discord.Commands.Builders | |||||
| return this; | return this; | ||||
| } | } | ||||
| private ModuleInfo BuildImpl(CommandService service, ModuleInfo parent = null) | |||||
| private ModuleInfo BuildImpl(CommandService service, IServiceProvider services, ModuleInfo parent = null) | |||||
| { | { | ||||
| //Default name to first alias | //Default name to first alias | ||||
| if (Name == null) | if (Name == null) | ||||
| @@ -124,7 +124,7 @@ namespace Discord.Commands.Builders | |||||
| { | { | ||||
| try | try | ||||
| { | { | ||||
| var moduleInstance = ReflectionUtils.CreateObject<IModuleBase>(TypeInfo, service, service._serviceProvider); | |||||
| var moduleInstance = ReflectionUtils.CreateObject<IModuleBase>(TypeInfo, service, services); | |||||
| moduleInstance.OnModuleBuilding(service); | moduleInstance.OnModuleBuilding(service); | ||||
| } | } | ||||
| catch (Exception) | catch (Exception) | ||||
| @@ -134,11 +134,11 @@ namespace Discord.Commands.Builders | |||||
| } | } | ||||
| } | } | ||||
| return new ModuleInfo(this, service, parent); | |||||
| return new ModuleInfo(this, service, services, parent); | |||||
| } | } | ||||
| public ModuleInfo Build(CommandService service) => BuildImpl(service); | |||||
| public ModuleInfo Build(CommandService service, IServiceProvider services) => BuildImpl(service, services); | |||||
| internal ModuleInfo Build(CommandService service, ModuleInfo parent) => BuildImpl(service, parent); | |||||
| internal ModuleInfo Build(CommandService service, IServiceProvider services, ModuleInfo parent) => BuildImpl(service, services, parent); | |||||
| } | } | ||||
| } | } | ||||
| @@ -42,8 +42,8 @@ namespace Discord.Commands | |||||
| } | } | ||||
| public static Task<Dictionary<Type, ModuleInfo>> BuildAsync(CommandService service, params TypeInfo[] validTypes) => BuildAsync(validTypes, service); | |||||
| public static async Task<Dictionary<Type, ModuleInfo>> BuildAsync(IEnumerable<TypeInfo> validTypes, CommandService service) | |||||
| public static Task<Dictionary<Type, ModuleInfo>> BuildAsync(CommandService service, IServiceProvider services, params TypeInfo[] validTypes) => BuildAsync(validTypes, service, services); | |||||
| public static async Task<Dictionary<Type, ModuleInfo>> BuildAsync(IEnumerable<TypeInfo> validTypes, CommandService service, IServiceProvider services) | |||||
| { | { | ||||
| /*if (!validTypes.Any()) | /*if (!validTypes.Any()) | ||||
| throw new InvalidOperationException("Could not find any valid modules from the given selection");*/ | throw new InvalidOperationException("Could not find any valid modules from the given selection");*/ | ||||
| @@ -63,11 +63,11 @@ namespace Discord.Commands | |||||
| var module = new ModuleBuilder(service, null); | var module = new ModuleBuilder(service, null); | ||||
| BuildModule(module, typeInfo, service); | |||||
| BuildSubTypes(module, typeInfo.DeclaredNestedTypes, builtTypes, service); | |||||
| BuildModule(module, typeInfo, service, services); | |||||
| BuildSubTypes(module, typeInfo.DeclaredNestedTypes, builtTypes, service, services); | |||||
| builtTypes.Add(typeInfo); | builtTypes.Add(typeInfo); | ||||
| result[typeInfo.AsType()] = module.Build(service); | |||||
| result[typeInfo.AsType()] = module.Build(service, services); | |||||
| } | } | ||||
| await service._cmdLogger.DebugAsync($"Successfully built {builtTypes.Count} modules.").ConfigureAwait(false); | await service._cmdLogger.DebugAsync($"Successfully built {builtTypes.Count} modules.").ConfigureAwait(false); | ||||
| @@ -75,7 +75,7 @@ namespace Discord.Commands | |||||
| return result; | return result; | ||||
| } | } | ||||
| private static void BuildSubTypes(ModuleBuilder builder, IEnumerable<TypeInfo> subTypes, List<TypeInfo> builtTypes, CommandService service) | |||||
| private static void BuildSubTypes(ModuleBuilder builder, IEnumerable<TypeInfo> subTypes, List<TypeInfo> builtTypes, CommandService service, IServiceProvider services) | |||||
| { | { | ||||
| foreach (var typeInfo in subTypes) | foreach (var typeInfo in subTypes) | ||||
| { | { | ||||
| @@ -87,15 +87,15 @@ namespace Discord.Commands | |||||
| builder.AddModule((module) => | builder.AddModule((module) => | ||||
| { | { | ||||
| BuildModule(module, typeInfo, service); | |||||
| BuildSubTypes(module, typeInfo.DeclaredNestedTypes, builtTypes, service); | |||||
| BuildModule(module, typeInfo, service, services); | |||||
| BuildSubTypes(module, typeInfo.DeclaredNestedTypes, builtTypes, service, services); | |||||
| }); | }); | ||||
| builtTypes.Add(typeInfo); | builtTypes.Add(typeInfo); | ||||
| } | } | ||||
| } | } | ||||
| private static void BuildModule(ModuleBuilder builder, TypeInfo typeInfo, CommandService service) | |||||
| private static void BuildModule(ModuleBuilder builder, TypeInfo typeInfo, CommandService service, IServiceProvider services) | |||||
| { | { | ||||
| var attributes = typeInfo.GetCustomAttributes(); | var attributes = typeInfo.GetCustomAttributes(); | ||||
| builder.TypeInfo = typeInfo; | builder.TypeInfo = typeInfo; | ||||
| @@ -141,12 +141,12 @@ namespace Discord.Commands | |||||
| { | { | ||||
| builder.AddCommand((command) => | builder.AddCommand((command) => | ||||
| { | { | ||||
| BuildCommand(command, typeInfo, method, service); | |||||
| BuildCommand(command, typeInfo, method, service, services); | |||||
| }); | }); | ||||
| } | } | ||||
| } | } | ||||
| private static void BuildCommand(CommandBuilder builder, TypeInfo typeInfo, MethodInfo method, CommandService service) | |||||
| private static void BuildCommand(CommandBuilder builder, TypeInfo typeInfo, MethodInfo method, CommandService service, IServiceProvider serviceprovider) | |||||
| { | { | ||||
| var attributes = method.GetCustomAttributes(); | var attributes = method.GetCustomAttributes(); | ||||
| @@ -192,7 +192,7 @@ namespace Discord.Commands | |||||
| { | { | ||||
| builder.AddParameter((parameter) => | builder.AddParameter((parameter) => | ||||
| { | { | ||||
| BuildParameter(parameter, paramInfo, pos++, count, service); | |||||
| BuildParameter(parameter, paramInfo, pos++, count, service, serviceprovider); | |||||
| }); | }); | ||||
| } | } | ||||
| @@ -228,7 +228,7 @@ namespace Discord.Commands | |||||
| builder.Callback = ExecuteCallback; | builder.Callback = ExecuteCallback; | ||||
| } | } | ||||
| private static void BuildParameter(ParameterBuilder builder, System.Reflection.ParameterInfo paramInfo, int position, int count, CommandService service) | |||||
| private static void BuildParameter(ParameterBuilder builder, System.Reflection.ParameterInfo paramInfo, int position, int count, CommandService service, IServiceProvider services) | |||||
| { | { | ||||
| var attributes = paramInfo.GetCustomAttributes(); | var attributes = paramInfo.GetCustomAttributes(); | ||||
| var paramType = paramInfo.ParameterType; | var paramType = paramInfo.ParameterType; | ||||
| @@ -246,7 +246,7 @@ namespace Discord.Commands | |||||
| builder.Summary = summary.Text; | builder.Summary = summary.Text; | ||||
| break; | break; | ||||
| case OverrideTypeReaderAttribute typeReader: | case OverrideTypeReaderAttribute typeReader: | ||||
| builder.TypeReader = GetTypeReader(service, paramType, typeReader.TypeReader); | |||||
| builder.TypeReader = GetTypeReader(service, paramType, typeReader.TypeReader, services); | |||||
| break; | break; | ||||
| case ParamArrayAttribute _: | case ParamArrayAttribute _: | ||||
| builder.IsMultiple = true; | builder.IsMultiple = true; | ||||
| @@ -286,7 +286,7 @@ namespace Discord.Commands | |||||
| } | } | ||||
| } | } | ||||
| private static TypeReader GetTypeReader(CommandService service, Type paramType, Type typeReaderType) | |||||
| private static TypeReader GetTypeReader(CommandService service, Type paramType, Type typeReaderType, IServiceProvider services) | |||||
| { | { | ||||
| var readers = service.GetTypeReaders(paramType); | var readers = service.GetTypeReaders(paramType); | ||||
| TypeReader reader = null; | TypeReader reader = null; | ||||
| @@ -297,7 +297,7 @@ namespace Discord.Commands | |||||
| } | } | ||||
| //We dont have a cached type reader, create one | //We dont have a cached type reader, create one | ||||
| reader = ReflectionUtils.CreateObject<TypeReader>(typeReaderType.GetTypeInfo(), service, service._serviceProvider); | |||||
| reader = ReflectionUtils.CreateObject<TypeReader>(typeReaderType.GetTypeInfo(), service, services); | |||||
| service.AddTypeReader(paramType, reader); | service.AddTypeReader(paramType, reader); | ||||
| return reader; | return reader; | ||||
| @@ -28,7 +28,7 @@ namespace Discord.Commands | |||||
| private readonly HashSet<ModuleInfo> _moduleDefs; | private readonly HashSet<ModuleInfo> _moduleDefs; | ||||
| private readonly CommandMap _map; | private readonly CommandMap _map; | ||||
| internal readonly IServiceProvider _serviceProvider; | |||||
| //internal readonly IServiceProvider _serviceProvider; | |||||
| internal readonly bool _caseSensitive, _throwOnError, _ignoreExtraArgs; | internal readonly bool _caseSensitive, _throwOnError, _ignoreExtraArgs; | ||||
| internal readonly char _separatorChar; | internal readonly char _separatorChar; | ||||
| @@ -43,10 +43,6 @@ namespace Discord.Commands | |||||
| public CommandService() : this(new CommandServiceConfig()) { } | public CommandService() : this(new CommandServiceConfig()) { } | ||||
| public CommandService(CommandServiceConfig config) | public CommandService(CommandServiceConfig config) | ||||
| { | { | ||||
| _serviceProvider = config.ServiceProvider | |||||
| ?? config.ServiceProviderFactory?.Invoke(this) | |||||
| ?? EmptyServiceProvider.Instance; | |||||
| _caseSensitive = config.CaseSensitiveCommands; | _caseSensitive = config.CaseSensitiveCommands; | ||||
| _throwOnError = config.ThrowOnError; | _throwOnError = config.ThrowOnError; | ||||
| _ignoreExtraArgs = config.IgnoreExtraArgs; | _ignoreExtraArgs = config.IgnoreExtraArgs; | ||||
| @@ -81,6 +77,10 @@ namespace Discord.Commands | |||||
| entityTypeReaders.Add(new Tuple<Type, Type>(typeof(IRole), typeof(RoleTypeReader<>))); | entityTypeReaders.Add(new Tuple<Type, Type>(typeof(IRole), typeof(RoleTypeReader<>))); | ||||
| entityTypeReaders.Add(new Tuple<Type, Type>(typeof(IUser), typeof(UserTypeReader<>))); | entityTypeReaders.Add(new Tuple<Type, Type>(typeof(IUser), typeof(UserTypeReader<>))); | ||||
| _entityTypeReaders = entityTypeReaders.ToImmutable(); | _entityTypeReaders = entityTypeReaders.ToImmutable(); | ||||
| //_serviceProvider = config.ServiceProvider | |||||
| // ?? config.ServiceProviderFactory?.Invoke(this) | |||||
| // ?? EmptyServiceProvider.Instance; | |||||
| } | } | ||||
| //Modules | //Modules | ||||
| @@ -101,8 +101,8 @@ namespace Discord.Commands | |||||
| _moduleLock.Release(); | _moduleLock.Release(); | ||||
| } | } | ||||
| } | } | ||||
| public Task<ModuleInfo> AddModuleAsync<T>() => AddModuleAsync(typeof(T)); | |||||
| public async Task<ModuleInfo> AddModuleAsync(Type type) | |||||
| public Task<ModuleInfo> AddModuleAsync<T>(IServiceProvider services) => AddModuleAsync(typeof(T), services); | |||||
| public async Task<ModuleInfo> AddModuleAsync(Type type, IServiceProvider services) | |||||
| { | { | ||||
| await _moduleLock.WaitAsync().ConfigureAwait(false); | await _moduleLock.WaitAsync().ConfigureAwait(false); | ||||
| try | try | ||||
| @@ -112,7 +112,7 @@ namespace Discord.Commands | |||||
| if (_typedModuleDefs.ContainsKey(type)) | if (_typedModuleDefs.ContainsKey(type)) | ||||
| throw new ArgumentException($"This module has already been added."); | throw new ArgumentException($"This module has already been added."); | ||||
| var module = (await ModuleClassBuilder.BuildAsync(this, typeInfo).ConfigureAwait(false)).FirstOrDefault(); | |||||
| var module = (await ModuleClassBuilder.BuildAsync(this, services, typeInfo).ConfigureAwait(false)).FirstOrDefault(); | |||||
| if (module.Value == default(ModuleInfo)) | if (module.Value == default(ModuleInfo)) | ||||
| throw new InvalidOperationException($"Could not build the module {type.FullName}, did you pass an invalid type?"); | throw new InvalidOperationException($"Could not build the module {type.FullName}, did you pass an invalid type?"); | ||||
| @@ -126,13 +126,13 @@ namespace Discord.Commands | |||||
| _moduleLock.Release(); | _moduleLock.Release(); | ||||
| } | } | ||||
| } | } | ||||
| public async Task<IEnumerable<ModuleInfo>> AddModulesAsync(Assembly assembly) | |||||
| public async Task<IEnumerable<ModuleInfo>> AddModulesAsync(Assembly assembly, IServiceProvider services) | |||||
| { | { | ||||
| await _moduleLock.WaitAsync().ConfigureAwait(false); | await _moduleLock.WaitAsync().ConfigureAwait(false); | ||||
| try | try | ||||
| { | { | ||||
| var types = await ModuleClassBuilder.SearchAsync(assembly, this).ConfigureAwait(false); | var types = await ModuleClassBuilder.SearchAsync(assembly, this).ConfigureAwait(false); | ||||
| var moduleDefs = await ModuleClassBuilder.BuildAsync(types, this).ConfigureAwait(false); | |||||
| var moduleDefs = await ModuleClassBuilder.BuildAsync(types, this, services).ConfigureAwait(false); | |||||
| foreach (var info in moduleDefs) | foreach (var info in moduleDefs) | ||||
| { | { | ||||
| @@ -280,12 +280,13 @@ namespace Discord.Commands | |||||
| return SearchResult.FromError(CommandError.UnknownCommand, "Unknown command."); | return SearchResult.FromError(CommandError.UnknownCommand, "Unknown command."); | ||||
| } | } | ||||
| public Task<IResult> ExecuteAsync(ICommandContext context, int argPos, /*IServiceProvider services = null,*/ MultiMatchHandling multiMatchHandling = MultiMatchHandling.Exception) | |||||
| => ExecuteAsync(context, context.Message.Content.Substring(argPos), /*services,*/ multiMatchHandling); | |||||
| public async Task<IResult> ExecuteAsync(ICommandContext context, string input, /*IServiceProvider services = null,*/ MultiMatchHandling multiMatchHandling = MultiMatchHandling.Exception) | |||||
| public Task<IResult> ExecuteAsync(ICommandContext context, int argPos, IServiceProvider services = null, MultiMatchHandling multiMatchHandling = MultiMatchHandling.Exception) | |||||
| => ExecuteAsync(context, context.Message.Content.Substring(argPos), services, multiMatchHandling); | |||||
| public async Task<IResult> ExecuteAsync(ICommandContext context, string input, IServiceProvider services = null, MultiMatchHandling multiMatchHandling = MultiMatchHandling.Exception) | |||||
| { | { | ||||
| //services = services ?? EmptyServiceProvider.Instance; | |||||
| using (var scope = _serviceProvider.CreateScope()) | |||||
| services = services ?? EmptyServiceProvider.Instance; | |||||
| //using (var scope = _serviceProvider.CreateScope()) | |||||
| using (var scope = services.CreateScope()) | |||||
| { | { | ||||
| var searchResult = Search(context, input); | var searchResult = Search(context, input); | ||||
| if (!searchResult.IsSuccess) | if (!searchResult.IsSuccess) | ||||
| @@ -21,10 +21,10 @@ namespace Discord.Commands | |||||
| /// <summary> Determines whether extra parameters should be ignored. </summary> | /// <summary> Determines whether extra parameters should be ignored. </summary> | ||||
| public bool IgnoreExtraArgs { get; set; } = false; | public bool IgnoreExtraArgs { get; set; } = false; | ||||
| /// <summary> Gets or sets the <see cref="IServiceProvider"/> to use. </summary> | |||||
| public IServiceProvider ServiceProvider { get; set; } = null; | |||||
| ///// <summary> Gets or sets the <see cref="IServiceProvider"/> to use. </summary> | |||||
| //public IServiceProvider ServiceProvider { get; set; } = null; | |||||
| /// <summary> Gets or sets a factory function for the <see cref="IServiceProvider"/> to use. </summary> | |||||
| public Func<CommandService, IServiceProvider> ServiceProviderFactory { get; set; } = null; | |||||
| ///// <summary> Gets or sets a factory function for the <see cref="IServiceProvider"/> to use. </summary> | |||||
| //public Func<CommandService, IServiceProvider> ServiceProviderFactory { get; set; } = null; | |||||
| } | } | ||||
| } | } | ||||
| @@ -24,7 +24,7 @@ namespace Discord.Commands | |||||
| //public TypeInfo TypeInfo { get; } | //public TypeInfo TypeInfo { get; } | ||||
| internal ModuleInfo(ModuleBuilder builder, CommandService service, ModuleInfo parent = null) | |||||
| internal ModuleInfo(ModuleBuilder builder, CommandService service, IServiceProvider services, ModuleInfo parent = null) | |||||
| { | { | ||||
| Service = service; | Service = service; | ||||
| @@ -40,7 +40,7 @@ namespace Discord.Commands | |||||
| Preconditions = BuildPreconditions(builder).ToImmutableArray(); | Preconditions = BuildPreconditions(builder).ToImmutableArray(); | ||||
| Attributes = BuildAttributes(builder).ToImmutableArray(); | Attributes = BuildAttributes(builder).ToImmutableArray(); | ||||
| Submodules = BuildSubmodules(builder, service).ToImmutableArray(); | |||||
| Submodules = BuildSubmodules(builder, service, services).ToImmutableArray(); | |||||
| } | } | ||||
| private static IEnumerable<string> BuildAliases(ModuleBuilder builder, CommandService service) | private static IEnumerable<string> BuildAliases(ModuleBuilder builder, CommandService service) | ||||
| @@ -70,12 +70,12 @@ namespace Discord.Commands | |||||
| return result; | return result; | ||||
| } | } | ||||
| private List<ModuleInfo> BuildSubmodules(ModuleBuilder parent, CommandService service) | |||||
| private List<ModuleInfo> BuildSubmodules(ModuleBuilder parent, CommandService service, IServiceProvider services) | |||||
| { | { | ||||
| var result = new List<ModuleInfo>(); | var result = new List<ModuleInfo>(); | ||||
| foreach (var submodule in parent.Modules) | foreach (var submodule in parent.Modules) | ||||
| result.Add(submodule.Build(service, this)); | |||||
| result.Add(submodule.Build(service, services, this)); | |||||
| return result; | return result; | ||||
| } | } | ||||