diff --git a/src/Discord.Net.Interactions/InteractionService.cs b/src/Discord.Net.Interactions/InteractionService.cs index a9d8ec16c..ac96f08ec 100644 --- a/src/Discord.Net.Interactions/InteractionService.cs +++ b/src/Discord.Net.Interactions/InteractionService.cs @@ -166,7 +166,8 @@ namespace Discord.Interactions [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 @@ namespace Discord.Interactions { 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 @@ namespace Discord.Interactions 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 000000000..874171175 --- /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); + } +}