@@ -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(); | |||
} | |||
} | |||
@@ -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<TypeReader> 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); | |||
} | |||
} | |||
} | |||
} |
@@ -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<TypeReader> _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<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) | |||
{ | |||
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; | |||
private string DebuggerDisplay => $"{Name}{(IsOptional ? " (Optional)" : "")}{(IsRemainder ? " (Remainder)" : "")}"; | |||
} | |||
} | |||
} |