How to create a structure like Discord.NET
I want to write an extension to a library ive started some time ago and was wondering how i could build up a similar system to Discord.NET
here is an example of what i mean
You have a
public class
that inherits InteractionModuleBase
and from that moment on you can create things like
And within that function you can access a Context
object which contains some data about the Interaction context
i was wondering how i could create / achieve such a thing and what the steps for that are22 Replies
Attributes are either used with reflections or source generators
What Discord.NET probably does, is it looks up any classes that inherit from
InteractionModuleBase
, then looks up all methods with [SlashCommand]
attribute, and registers them... somewhereyes it does that
you have to call something like RegisterModulesAsync and then pass in the entry assembly
Context
is likely a property on InteractionModuleBase
and thats how you get access to itlike Assembly.GetEntryAssembly or whatever it was
and then you need to create an event handler that executes the interaction with the corresponding function / attribute
yes Context comes from InteractionModuleBase
i love the concept and id love to know more about it cause it seems so convinient when applied properly
In pseudocode, it would be something like
and when i have a list of functions with attributes i could check for example if the given command is "some-command" and then call the function with the given parameters?
Yep
and i assume if the class or function is anything but public it wont get picked up as a candidate for that list?
With reflections/sourcegen it's not a limitation
You can exclude non-public classes and methods, sure
But you don't have to
Discord.NET uses reflection i assume since the parameter to pass in the entry assemlbly
Probably reflections, yes
so my general workflow should be to get all classes that inherit my target class and then get all functions from that class that uses a specific attribute and such?
It's easier, albeit less performant than source generators
Yep
interesting
ill get back to it later if i have followup questions
thanks!
Anytime :Ok:
performance isnt really a priority for that project tbh
where would i keep the "database" of my functions and how would i structure them
do i keep them inside of the BaseClient or the InteractionBase or perhaps a static Utils class with Lists of Objects descripting the functions and Queue
You mean storing the methods you got via reflections?
yes
so i can later call them
Anywhere and anyhow that suits you, really
oki
so its totally fine if i just put them into an object with additional info like parameters and the attributes they carry and then just store them in a static List or dictionary
Sure
I've decided to store both queue and modules inside of the base client as it will be a thing that should stay existent over the entire runtime duration
This should also allow for a multi client structure if someone really wants to
Ive gotten pretty far into the process
This is a structure ive come up with
And its working pretty well, i can now register my modules via Assembly or direct class reference in a <T> type, this is how my InteractionModule object looks like
but now im wondering how i can achieve the ability to call my ModuleInteractionMethod using both optional parameters and only required ones
for example my function will call if i do
but will not be called if i do
This is how my function is getting set
for reference on how im registering my modules
ive fixed that issue, however, now i have an issue with my Context / InteractionBase class
How can i make sure it sets the proper values on every call it makes, my approach would be to also save that class / instance inside of my module object so i can modify the Context object to my needs but now my InteractionBase is always null
this is how i retrieve it:
module.ModuleInteractionBase = (InteractionBase)Activator.CreateInstance(moduleType);
update: the InteractionBase values seem to get set as indicated by this JSON:
Which makes me believe that the InteractionBase my class inherits is a different one from the one im setting