diff --git a/src/Discord.Net.Commands/Builders/ModuleClassBuilder.cs b/src/Discord.Net.Commands/Builders/ModuleClassBuilder.cs index 5a3a1f25a..15957ccc6 100644 --- a/src/Discord.Net.Commands/Builders/ModuleClassBuilder.cs +++ b/src/Discord.Net.Commands/Builders/ModuleClassBuilder.cs @@ -1,6 +1,7 @@ using System; using System.Linq; using System.Collections.Generic; +using System.Collections.Immutable; using System.Reflection; using System.Threading.Tasks; @@ -245,7 +246,7 @@ namespace Discord.Commands builder.Summary = summary.Text; break; case OverrideTypeReaderAttribute typeReader: - builder.TypeReader = GetTypeReader(service, paramType, typeReader.TypeReader); + builder.TypeReaders = ImmutableList.Create(GetTypeReader(service, paramType, typeReader.TypeReader)); break; case ParamArrayAttribute _: builder.IsMultiple = true; @@ -271,17 +272,9 @@ namespace Discord.Commands builder.ParameterType = paramType; - if (builder.TypeReader == null) + if (builder.TypeReaders == null || builder.TypeReaders.Count == 0) { - var readers = service.GetTypeReaders(paramType); - TypeReader reader = null; - - if (readers != null) - reader = readers.FirstOrDefault().Value; - else - reader = service.GetDefaultTypeReader(paramType); - - builder.TypeReader = reader; + builder.TypeReaders = service.GetTypeReaders(paramType).Values.ToImmutableList(); } } diff --git a/src/Discord.Net.Commands/Builders/ParameterBuilder.cs b/src/Discord.Net.Commands/Builders/ParameterBuilder.cs index d1782d7ea..971ea61aa 100644 --- a/src/Discord.Net.Commands/Builders/ParameterBuilder.cs +++ b/src/Discord.Net.Commands/Builders/ParameterBuilder.cs @@ -1,8 +1,9 @@ using System; +using System.Collections.Generic; +using System.Collections.Immutable; using System.Linq; using System.Reflection; -using System.Collections.Generic; namespace Discord.Commands.Builders { @@ -15,7 +16,7 @@ namespace Discord.Commands.Builders public string Name { get; internal set; } public Type ParameterType { get; internal set; } - public TypeReader TypeReader { get; set; } + public IReadOnlyCollection TypeReaders { get; set; } public bool IsOptional { get; set; } public bool IsRemainder { get; set; } public bool IsMultiple { get; set; } @@ -45,13 +46,13 @@ namespace Discord.Commands.Builders internal void SetType(Type type) { - var readers = Command.Module.Service.GetTypeReaders(type); - if (readers != null) - TypeReader = readers.FirstOrDefault().Value; + var readers = Command.Module.Service.GetTypeReaders(type).Values.ToImmutableList(); + if (readers.Count > 1) + TypeReaders = readers; else - TypeReader = Command.Module.Service.GetDefaultTypeReader(type); + TypeReaders = ImmutableList.Create(Command.Module.Service.GetDefaultTypeReader(type)); - if (TypeReader == null) + if (TypeReaders.Count == 0) throw new InvalidOperationException($"{type} does not have a TypeReader registered for it. Parameter: {Name} in {Command.PrimaryAlias}"); if (type.GetTypeInfo().IsValueType) @@ -100,10 +101,10 @@ namespace Discord.Commands.Builders internal ParameterInfo Build(CommandInfo info) { - if (TypeReader == null) + if (TypeReaders == null || TypeReaders.Count == 0) throw new InvalidOperationException($"No type reader found for type {ParameterType.Name}, one must be specified"); return new ParameterInfo(this, info, Command.Module.Service); } } -} \ No newline at end of file +} diff --git a/src/Discord.Net.Commands/Info/ParameterInfo.cs b/src/Discord.Net.Commands/Info/ParameterInfo.cs index 4a56415e5..6e6858a70 100644 --- a/src/Discord.Net.Commands/Info/ParameterInfo.cs +++ b/src/Discord.Net.Commands/Info/ParameterInfo.cs @@ -1,15 +1,15 @@ -using Discord.Commands.Builders; using System; using System.Collections.Generic; using System.Collections.Immutable; using System.Threading.Tasks; using Microsoft.Extensions.DependencyInjection; +using Discord.Commands.Builders; namespace Discord.Commands { public class ParameterInfo { - private readonly TypeReader _reader; + private readonly IReadOnlyCollection _readers; public CommandInfo Command { get; } public string Name { get; } @@ -39,7 +39,7 @@ namespace Discord.Commands Preconditions = builder.Preconditions.ToImmutableArray(); Attributes = builder.Attributes.ToImmutableArray(); - _reader = builder.TypeReader; + _readers = builder.TypeReaders; } public async Task CheckPreconditionsAsync(ICommandContext context, object arg, IServiceProvider services = null) @@ -59,10 +59,23 @@ namespace Discord.Commands public async Task ParseAsync(ICommandContext context, string input, IServiceProvider services = null) { services = services ?? EmptyServiceProvider.Instance; - return await _reader.ReadAsync(context, input, services).ConfigureAwait(false); + var failedResults = new List(); + foreach (var reader in _readers) + { + var result = await reader.ReadAsync(context, input, services).ConfigureAwait(false); + if (result.IsSuccess) + return result; + + failedResults.Add(result); + } + + if (failedResults.Count == 1) + return failedResults[0]; + + return TypeReaderResult.FromError(CommandError.Unsuccessful, "None of the registered TypeReaders could parse the input."); } public override string ToString() => Name; private string DebuggerDisplay => $"{Name}{(IsOptional ? " (Optional)" : "")}{(IsRemainder ? " (Remainder)" : "")}"; } -} \ No newline at end of file +}