Browse Source

Add NullableTypeReader.

Primitives now also load a NullableTypeReader<T> and any value types that get a typereader added will also have a NullableTypeReader<T> added for it.
pull/785/head
AntiTcb 8 years ago
parent
commit
104e898d88
2 changed files with 50 additions and 7 deletions
  1. +14
    -7
      src/Discord.Net.Commands/CommandService.cs
  2. +36
    -0
      src/Discord.Net.Commands/Readers/NullableTypeReader.cs

+ 14
- 7
src/Discord.Net.Commands/CommandService.cs View File

@@ -8,7 +8,6 @@ using System.Linq;
using System.Reflection; using System.Reflection;
using System.Threading; using System.Threading;
using System.Threading.Tasks; using System.Threading.Tasks;
using Microsoft.Extensions.DependencyInjection;


namespace Discord.Commands namespace Discord.Commands
{ {
@@ -57,7 +56,10 @@ namespace Discord.Commands


_defaultTypeReaders = new ConcurrentDictionary<Type, TypeReader>(); _defaultTypeReaders = new ConcurrentDictionary<Type, TypeReader>();
foreach (var type in PrimitiveParsers.SupportedTypes) foreach (var type in PrimitiveParsers.SupportedTypes)
{
_defaultTypeReaders[type] = PrimitiveTypeReader.Create(type); _defaultTypeReaders[type] = PrimitiveTypeReader.Create(type);
_defaultTypeReaders[typeof(Nullable<>).MakeGenericType(type)] = NullableTypeReader.Create(type, _defaultTypeReaders[type]);
}


_defaultTypeReaders[typeof(string)] = _defaultTypeReaders[typeof(string)] =
new PrimitiveTypeReader<string>((string x, out string y) => { y = x; return true; }, 0); new PrimitiveTypeReader<string>((string x, out string y) => { y = x; return true; }, 0);
@@ -190,17 +192,23 @@ namespace Discord.Commands
return true; return true;
} }


//Type Readers
//Type Readers
public void AddTypeReader<T>(TypeReader reader) public void AddTypeReader<T>(TypeReader reader)
{
var readers = _typeReaders.GetOrAdd(typeof(T), x => new ConcurrentDictionary<Type, TypeReader>());
readers[reader.GetType()] = reader;
}
=> AddTypeReader(typeof(T), reader);
public void AddTypeReader(Type type, TypeReader reader) public void AddTypeReader(Type type, TypeReader reader)
{ {
var readers = _typeReaders.GetOrAdd(type, x => new ConcurrentDictionary<Type, TypeReader>()); var readers = _typeReaders.GetOrAdd(type, x => new ConcurrentDictionary<Type, TypeReader>());
readers[reader.GetType()] = reader; 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<Type, TypeReader>());
var nullableReader = NullableTypeReader.Create(valueType, valueTypeReader);
readers[nullableReader.GetType()] = nullableReader;
}
internal IDictionary<Type, TypeReader> GetTypeReaders(Type type) internal IDictionary<Type, TypeReader> GetTypeReaders(Type type)
{ {
if (_typeReaders.TryGetValue(type, out var definedTypeReaders)) if (_typeReaders.TryGetValue(type, out var definedTypeReaders))
@@ -233,7 +241,6 @@ namespace Discord.Commands
} }
return null; return null;
} }

//Execution //Execution
public SearchResult Search(ICommandContext context, int argPos) public SearchResult Search(ICommandContext context, int argPos)
=> Search(context, context.Message.Content.Substring(argPos)); => Search(context, context.Message.Content.Substring(argPos));


+ 36
- 0
src/Discord.Net.Commands/Readers/NullableTypeReader.cs View File

@@ -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<T> : TypeReader
where T : struct
{
private readonly TypeReader _baseTypeReader;

public NullableTypeReader(TypeReader baseTypeReader)
{
_baseTypeReader = baseTypeReader;
}

public override async Task<TypeReaderResult> 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); ;
}
}
}

Loading…
Cancel
Save