| @@ -1,6 +1,7 @@ | |||||
| using System; | using System; | ||||
| using System.Linq; | using System.Linq; | ||||
| using System.Collections.Generic; | using System.Collections.Generic; | ||||
| using System.Collections.Immutable; | |||||
| using System.Reflection; | using System.Reflection; | ||||
| using System.Threading.Tasks; | using System.Threading.Tasks; | ||||
| @@ -245,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.TypeReaders = ImmutableList.Create(GetTypeReader(service, paramType, typeReader.TypeReader)); | |||||
| break; | break; | ||||
| case ParamArrayAttribute _: | case ParamArrayAttribute _: | ||||
| builder.IsMultiple = true; | builder.IsMultiple = true; | ||||
| @@ -271,17 +272,9 @@ namespace Discord.Commands | |||||
| builder.ParameterType = paramType; | 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(); | |||||
| } | } | ||||
| } | } | ||||
| @@ -1,8 +1,9 @@ | |||||
| using System; | using System; | ||||
| using System.Collections.Generic; | |||||
| using System.Collections.Immutable; | |||||
| using System.Linq; | using System.Linq; | ||||
| using System.Reflection; | using System.Reflection; | ||||
| using System.Collections.Generic; | |||||
| namespace Discord.Commands.Builders | namespace Discord.Commands.Builders | ||||
| { | { | ||||
| @@ -15,7 +16,7 @@ namespace Discord.Commands.Builders | |||||
| public string Name { get; internal set; } | public string Name { get; internal set; } | ||||
| public Type ParameterType { get; internal set; } | public Type ParameterType { get; internal set; } | ||||
| public TypeReader TypeReader { get; set; } | |||||
| public IReadOnlyCollection<TypeReader> TypeReaders { get; set; } | |||||
| public bool IsOptional { get; set; } | public bool IsOptional { get; set; } | ||||
| public bool IsRemainder { get; set; } | public bool IsRemainder { get; set; } | ||||
| public bool IsMultiple { get; set; } | public bool IsMultiple { get; set; } | ||||
| @@ -45,13 +46,13 @@ namespace Discord.Commands.Builders | |||||
| internal void SetType(Type type) | 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 | 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}"); | throw new InvalidOperationException($"{type} does not have a TypeReader registered for it. Parameter: {Name} in {Command.PrimaryAlias}"); | ||||
| if (type.GetTypeInfo().IsValueType) | if (type.GetTypeInfo().IsValueType) | ||||
| @@ -100,10 +101,10 @@ namespace Discord.Commands.Builders | |||||
| internal ParameterInfo Build(CommandInfo info) | 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"); | throw new InvalidOperationException($"No type reader found for type {ParameterType.Name}, one must be specified"); | ||||
| return new ParameterInfo(this, info, Command.Module.Service); | return new ParameterInfo(this, info, Command.Module.Service); | ||||
| } | } | ||||
| } | } | ||||
| } | |||||
| } | |||||
| @@ -1,15 +1,15 @@ | |||||
| using Discord.Commands.Builders; | |||||
| using System; | using System; | ||||
| using System.Collections.Generic; | using System.Collections.Generic; | ||||
| using System.Collections.Immutable; | using System.Collections.Immutable; | ||||
| using System.Threading.Tasks; | using System.Threading.Tasks; | ||||
| using Microsoft.Extensions.DependencyInjection; | using Microsoft.Extensions.DependencyInjection; | ||||
| using Discord.Commands.Builders; | |||||
| namespace Discord.Commands | namespace Discord.Commands | ||||
| { | { | ||||
| public class ParameterInfo | public class ParameterInfo | ||||
| { | { | ||||
| private readonly TypeReader _reader; | |||||
| private readonly IReadOnlyCollection<TypeReader> _readers; | |||||
| public CommandInfo Command { get; } | public CommandInfo Command { get; } | ||||
| public string Name { get; } | public string Name { get; } | ||||
| @@ -39,7 +39,7 @@ namespace Discord.Commands | |||||
| Preconditions = builder.Preconditions.ToImmutableArray(); | Preconditions = builder.Preconditions.ToImmutableArray(); | ||||
| Attributes = builder.Attributes.ToImmutableArray(); | Attributes = builder.Attributes.ToImmutableArray(); | ||||
| _reader = builder.TypeReader; | |||||
| _readers = builder.TypeReaders; | |||||
| } | } | ||||
| public async Task<PreconditionResult> CheckPreconditionsAsync(ICommandContext context, object arg, IServiceProvider services = null) | public async Task<PreconditionResult> CheckPreconditionsAsync(ICommandContext context, object arg, IServiceProvider services = null) | ||||
| @@ -59,10 +59,23 @@ namespace Discord.Commands | |||||
| public async Task<TypeReaderResult> ParseAsync(ICommandContext context, string input, IServiceProvider services = null) | public async Task<TypeReaderResult> ParseAsync(ICommandContext context, string input, IServiceProvider services = null) | ||||
| { | { | ||||
| services = services ?? EmptyServiceProvider.Instance; | services = services ?? EmptyServiceProvider.Instance; | ||||
| return await _reader.ReadAsync(context, input, services).ConfigureAwait(false); | |||||
| var failedResults = new List<TypeReaderResult>(); | |||||
| 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; | public override string ToString() => Name; | ||||
| private string DebuggerDisplay => $"{Name}{(IsOptional ? " (Optional)" : "")}{(IsRemainder ? " (Remainder)" : "")}"; | private string DebuggerDisplay => $"{Name}{(IsOptional ? " (Optional)" : "")}{(IsRemainder ? " (Remainder)" : "")}"; | ||||
| } | } | ||||
| } | |||||
| } | |||||