TypeConverters
TypeConverters are responsible for registering command parameters to Discord and parsing the user inputs into method parameters.
By default, TypeConverters for the following types are provided with Discord.Interactions library.
- Implementations of IUser
- Implementations of IChannel
- Implementations of IRole
- Implementations of IMentionable
string
float
,double
,decimal
bool
char
sbyte
,byte
int16
,int32
,int64
uint16
,uint32
,uint64
enum
DateTime
TimeSpan
Creating TypeConverters
Depending on your needs, there are two types of TypeConverters you can create:
- Concrete type
- Generic type
A valid converter must inherit TypeConverter base type. And override the abstract base methods.
CanConvertTo() Method
This method is used by Interaction Service to search for alternative Type Converters.
Interaction Services determines the most suitable TypeConverter for a parameter type in the following order:
- It searches for a TypeConverter that is registered to specifically target that parameter type
- It searches for a TypeConverter that returns
true
when itsCanConvertTo()
method is invoked for thaty parameter type. - It searches for a generic
TypeConverter<T>
with a matching type constraint. If there are more multiple matches, the one whose type constraint is the most specialized will be chosen.
Note
Alternatively, you can use the generic variant (TypeConverter<T>
) of the
TypeConverter base class which implements the following method body for CanConvertTo()
method
public sealed override bool CanConvertTo (Type type) =>
typeof(T).IsAssignableFrom(type);
GetDiscordType() Method
This method is used by InteractionService to determine the Discord Application Command Option type of a parameter type.
ReadAsync() Method
This method is used by InteractionService to parse the user input. This method should return FromSuccess if the parsing operation is successful, otherwise it should return FromError . The inner logic of this method is totally up to you, however you should avoid using long running code.
Write() Method
This method is used to configure the Discord Application Command Option before it gets registered to Discord.
Command Option is configured by modifying the ApplicationCommandOptionProperties
instance.
Warning
The default parameter building pipeline is isolated and will not be disturbed by the TypeConverter workflow. But changes made in this method will override the values generated by the InteractionService for a Discord Application Command Option.
Example Enum TypeConverter
internal sealed class EnumConverter<T> : TypeConverter<T> where T : struct, Enum
{
public override ApplicationCommandOptionType GetDiscordType() => ApplicationCommandOptionType.String;
public override Task<TypeConverterResult> ReadAsync(IInteractionCommandContext context, SocketSlashCommandDataOption option, IServiceProvider services)
{
if (Enum.TryParse<T>((string)option.Value, out var result))
return Task.FromResult(TypeConverterResult.FromSuccess(result));
else
return Task.FromResult(TypeConverterResult.FromError(InteractionCommandError.ConvertFailed, $"Value {option.Value} cannot be converted to {nameof(T)}"));
}
public override void Write(ApplicationCommandOptionProperties properties, IParameterInfo parameterInfo)
{
var names = Enum.GetNames(typeof(T));
if (names.Length <= 25)
{
var choices = new List<ApplicationCommandOptionChoiceProperties>();
foreach (var name in names)
choices.Add(new ApplicationCommandOptionChoiceProperties
{
Name = name,
Value = name
});
properties.Choices = choices;
}
}
}
Important
TypeConverters must be registered prior to module discovery. If Interaction Service encounters a parameter type that doesn't belong to any of the registered [TypeConverters] during this phase, it will throw an exception.
Concrete TypeConverters
Registering Concrete TypeConverters are as simple as creating an instance of your custom converter and invoking AddTypeConverter()
method.
interactionService.AddTypeConverter<string[]>(new StringArrayConverter());
Generic TypeConverters
To register a generic TypeConverter<T>
, you need to invoke the AddGenericTypeConverter()
method of the Interaction Service class.
You need to pass the type of your TypeConverter<T>
and a target base type to this method.
For instance, to register the previously mentioned enum converter the following can be used:
interactionService.AddGenericTypeConverter<Enum>(typeof(EnumConverter<>));
Interaction service checks if the target base type satisfies the type constraints of the Generic TypeConverter
class.
Note
Dependencies of Generic TypeConverters are also resolved using the Dependency Injection pattern.