From 104e898d88ad672605b81e76f9878351f4888e0a Mon Sep 17 00:00:00 2001 From: AntiTcb Date: Sun, 6 Aug 2017 20:37:49 -0400 Subject: [PATCH] Add NullableTypeReader. Primitives now also load a NullableTypeReader and any value types that get a typereader added will also have a NullableTypeReader added for it. --- src/Discord.Net.Commands/CommandService.cs | 21 +++++++---- .../Readers/NullableTypeReader.cs | 36 +++++++++++++++++++ 2 files changed, 50 insertions(+), 7 deletions(-) create mode 100644 src/Discord.Net.Commands/Readers/NullableTypeReader.cs diff --git a/src/Discord.Net.Commands/CommandService.cs b/src/Discord.Net.Commands/CommandService.cs index 6ea2abcf3..e3a67da4e 100644 --- a/src/Discord.Net.Commands/CommandService.cs +++ b/src/Discord.Net.Commands/CommandService.cs @@ -8,7 +8,6 @@ using System.Linq; using System.Reflection; using System.Threading; using System.Threading.Tasks; -using Microsoft.Extensions.DependencyInjection; namespace Discord.Commands { @@ -57,7 +56,10 @@ namespace Discord.Commands _defaultTypeReaders = new ConcurrentDictionary(); foreach (var type in PrimitiveParsers.SupportedTypes) + { _defaultTypeReaders[type] = PrimitiveTypeReader.Create(type); + _defaultTypeReaders[typeof(Nullable<>).MakeGenericType(type)] = NullableTypeReader.Create(type, _defaultTypeReaders[type]); + } _defaultTypeReaders[typeof(string)] = new PrimitiveTypeReader((string x, out string y) => { y = x; return true; }, 0); @@ -190,17 +192,23 @@ namespace Discord.Commands return true; } - //Type Readers + //Type Readers public void AddTypeReader(TypeReader reader) - { - var readers = _typeReaders.GetOrAdd(typeof(T), x => new ConcurrentDictionary()); - readers[reader.GetType()] = reader; - } + => AddTypeReader(typeof(T), reader); public void AddTypeReader(Type type, TypeReader reader) { var readers = _typeReaders.GetOrAdd(type, x => new ConcurrentDictionary()); readers[reader.GetType()] = reader; + + if (type.GetTypeInfo().IsValueType) + AddNullableTypeReader(type, reader); } + internal void AddNullableTypeReader(Type valueType, TypeReader valueTypeReader) + { + var readers = _typeReaders.GetOrAdd(typeof(Nullable<>).MakeGenericType(valueType), x => new ConcurrentDictionary()); + var nullableReader = NullableTypeReader.Create(valueType, valueTypeReader); + readers[nullableReader.GetType()] = nullableReader; + } internal IDictionary GetTypeReaders(Type type) { if (_typeReaders.TryGetValue(type, out var definedTypeReaders)) @@ -233,7 +241,6 @@ namespace Discord.Commands } return null; } - //Execution public SearchResult Search(ICommandContext context, int argPos) => Search(context, context.Message.Content.Substring(argPos)); diff --git a/src/Discord.Net.Commands/Readers/NullableTypeReader.cs b/src/Discord.Net.Commands/Readers/NullableTypeReader.cs new file mode 100644 index 000000000..0342f3170 --- /dev/null +++ b/src/Discord.Net.Commands/Readers/NullableTypeReader.cs @@ -0,0 +1,36 @@ +using System; +using System.Linq; +using System.Reflection; +using System.Threading.Tasks; + +namespace Discord.Commands +{ + internal static class NullableTypeReader + { + public static TypeReader Create(Type type, TypeReader reader) + { + if (reader == null) + return null; + var constructor = typeof(NullableTypeReader<>).MakeGenericType(type).GetTypeInfo().DeclaredConstructors.First(); + return (TypeReader)constructor.Invoke(new object[] { reader }); + } + } + + internal class NullableTypeReader : TypeReader + where T : struct + { + private readonly TypeReader _baseTypeReader; + + public NullableTypeReader(TypeReader baseTypeReader) + { + _baseTypeReader = baseTypeReader; + } + + public override async Task Read(ICommandContext context, string input, IServiceProvider services) + { + if (string.Equals(input, "null", StringComparison.OrdinalIgnoreCase) || string.Equals(input, "nothing", StringComparison.OrdinalIgnoreCase)) + return TypeReaderResult.FromSuccess(new T?()); + return await _baseTypeReader.Read(context, input, services); ; + } + } +}