Add NullableTypeReader (#785)
* 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. * Remove unnecessary null check. * Added docstrings.
This commit is contained in:
committed by
Christopher F
parent
4205d68b5a
commit
cb0ff7817d
@@ -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<Type, TypeReader>();
|
||||
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>((string x, out string y) => { y = x; return true; }, 0);
|
||||
@@ -190,17 +192,35 @@ namespace Discord.Commands
|
||||
return true;
|
||||
}
|
||||
|
||||
//Type Readers
|
||||
//Type Readers
|
||||
/// <summary>
|
||||
/// Adds a custom <see cref="TypeReader"/> to this <see cref="CommandService"/> for the supplied object type.
|
||||
/// If <typeparamref name="T"/> is a <see cref="ValueType"/>, a <see cref="NullableTypeReader{T}"/> will also be added.
|
||||
/// </summary>
|
||||
/// <typeparam name="T">The object type to be read by the <see cref="TypeReader"/>.</typeparam>
|
||||
/// <param name="reader">An instance of the <see cref="TypeReader"/> to be added.</param>
|
||||
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);
|
||||
/// <summary>
|
||||
/// Adds a custom <see cref="TypeReader"/> to this <see cref="CommandService"/> for the supplied object type.
|
||||
/// If <paramref name="type"/> is a <see cref="ValueType"/>, a <see cref="NullableTypeReader{T}"/> for the value type will also be added.
|
||||
/// </summary>
|
||||
/// <param name="type">A <see cref="Type"/> instance for the type to be read.</param>
|
||||
/// <param name="reader">An instance of the <see cref="TypeReader"/> to be added.</param>
|
||||
public void AddTypeReader(Type type, TypeReader reader)
|
||||
{
|
||||
var readers = _typeReaders.GetOrAdd(type, x => new ConcurrentDictionary<Type, TypeReader>());
|
||||
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)
|
||||
{
|
||||
if (_typeReaders.TryGetValue(type, out var definedTypeReaders))
|
||||
|
||||
34
src/Discord.Net.Commands/Readers/NullableTypeReader.cs
Normal file
34
src/Discord.Net.Commands/Readers/NullableTypeReader.cs
Normal file
@@ -0,0 +1,34 @@
|
||||
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)
|
||||
{
|
||||
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); ;
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user