From ccc365edfd7db75ffc1e3a60ed5c1d74136ace76 Mon Sep 17 00:00:00 2001 From: Quin Lynch <49576606+quinchs@users.noreply.github.com> Date: Fri, 24 Dec 2021 10:37:57 -0400 Subject: [PATCH] Add nullable type converter to Interaction service (#1996) * Add nullable type converter to Interaction service * update NullableConverter CanConvertTo body --- .../InteractionService.cs | 10 +++++-- .../TypeConverters/NullableConverter.cs | 29 +++++++++++++++++++ 2 files changed, 36 insertions(+), 3 deletions(-) create mode 100644 src/Discord.Net.Interactions/TypeConverters/NullableConverter.cs diff --git a/src/Discord.Net.Interactions/InteractionService.cs b/src/Discord.Net.Interactions/InteractionService.cs index a9d8ec16cc..ac96f08ecd 100644 --- a/src/Discord.Net.Interactions/InteractionService.cs +++ b/src/Discord.Net.Interactions/InteractionService.cs @@ -166,7 +166,8 @@ private InteractionService (Func getRestClient, InteractionSe [typeof(IUser)] = typeof(DefaultUserConverter<>), [typeof(IMentionable)] = typeof(DefaultMentionableConverter<>), [typeof(IConvertible)] = typeof(DefaultValueConverter<>), - [typeof(Enum)] = typeof(EnumConverter<>) + [typeof(Enum)] = typeof(EnumConverter<>), + [typeof(Nullable<>)] = typeof(NullableConverter<>), }; _typeConverters = new ConcurrentDictionary @@ -693,8 +694,8 @@ internal TypeConverter GetTypeConverter (Type type, IServiceProvider services = { if (_typeConverters.TryGetValue(type, out var specific)) return specific; - - else if (_genericTypeConverters.Any(x => x.Key.IsAssignableFrom(type))) + else if (_genericTypeConverters.Any(x => x.Key.IsAssignableFrom(type) + || (x.Key.IsGenericTypeDefinition && type.IsGenericType && x.Key.GetGenericTypeDefinition() == type.GetGenericTypeDefinition()))) { services ??= EmptyServiceProvider.Instance; @@ -927,6 +928,9 @@ private Type GetMostSpecificTypeConverter (Type type) if (_genericTypeConverters.TryGetValue(type, out var matching)) return matching; + if (type.IsGenericType && _genericTypeConverters.TryGetValue(type.GetGenericTypeDefinition(), out var genericDefinition)) + return genericDefinition; + var typeInterfaces = type.GetInterfaces(); var candidates = _genericTypeConverters.Where(x => x.Key.IsAssignableFrom(type)) .OrderByDescending(x => typeInterfaces.Count(y => y.IsAssignableFrom(x.Key))); diff --git a/src/Discord.Net.Interactions/TypeConverters/NullableConverter.cs b/src/Discord.Net.Interactions/TypeConverters/NullableConverter.cs new file mode 100644 index 0000000000..8741711754 --- /dev/null +++ b/src/Discord.Net.Interactions/TypeConverters/NullableConverter.cs @@ -0,0 +1,29 @@ +using System; +using System.Threading.Tasks; + +namespace Discord.Interactions +{ + internal class NullableConverter : TypeConverter + { + private readonly TypeConverter _typeConverter; + + public NullableConverter(InteractionService interactionService, IServiceProvider services) + { + var type = Nullable.GetUnderlyingType(typeof(T)); + + if (type is null) + throw new ArgumentException($"No type {nameof(TypeConverter)} is defined for this {type.FullName}", "type"); + + _typeConverter = interactionService.GetTypeConverter(type, services); + } + + public override ApplicationCommandOptionType GetDiscordType() + => _typeConverter.GetDiscordType(); + + public override Task ReadAsync(IInteractionContext context, IApplicationCommandInteractionDataOption option, IServiceProvider services) + => _typeConverter.ReadAsync(context, option, services); + + public override void Write(ApplicationCommandOptionProperties properties, IParameterInfo parameter) + => _typeConverter.Write(properties, parameter); + } +}