Browse Source

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.
tags/2.0.0-beta
Alex Gravely Christopher F 7 years ago
parent
commit
cb0ff7817d
2 changed files with 60 additions and 6 deletions
  1. +26
    -6
      src/Discord.Net.Commands/CommandService.cs
  2. +34
    -0
      src/Discord.Net.Commands/Readers/NullableTypeReader.cs

+ 26
- 6
src/Discord.Net.Commands/CommandService.cs View File

@@ -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
- 0
src/Discord.Net.Commands/Readers/NullableTypeReader.cs View 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); ;
}
}
}

Loading…
Cancel
Save