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.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);
|
||||||
@@ -191,15 +193,33 @@ namespace Discord.Commands
|
|||||||
}
|
}
|
||||||
|
|
||||||
//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)
|
public void AddTypeReader<T>(TypeReader reader)
|
||||||
{
|
=> AddTypeReader(typeof(T), reader);
|
||||||
var readers = _typeReaders.GetOrAdd(typeof(T), x => new ConcurrentDictionary<Type, TypeReader>());
|
/// <summary>
|
||||||
readers[reader.GetType()] = reader;
|
/// 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)
|
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)
|
||||||
{
|
{
|
||||||
|
|||||||
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