lundi 28 décembre 2020

C# attributes and methods

Good day, everyone, recently I've come across the Discord.NET Api and was in love with the way Commands were handled. Essentially, to add a new Command that is executed when you write !ping, you can do this:

[Command("ping")]
public async Task Ping()
{
    //some logic here
}

And I really liked the easy nature of integrating new commands in an already existing API. So I wanted to recreate what was going on. In the beginning I was absolutely confused by the introduction of metaprogramming, but now feel a little more comfortable, so I tried to start, and designed an Attribute that was only assignable to methods:


[AttributeUsage(AttributeTargets.Method)]
    public class Command : Attribute
    {
        
        public string Name { get; set; }

        public Command(string name)
        {
            Name = name;
        }
        public Command()
        {
            Name = string.Empty;
        }
    }

Basic idea then is, that when my Console gets a command, I can run a method that has the command attribute and the name of what was entered in the console. So when I enter "ping" in the console, the below method is going to be executed.

[Command("ping")]
public void Ping()
{
    //do sth 
}

Now to the complicated part. How do I find and especially run that method? That's where I'm stuck right now. I really don't find anything helpful about that question on the .Net documentary or here on stackoverflow. Here is my attempt anyway:

public void Handle(string command)
{
    var methods = from t in Assembly.GetExecutingAssembly().GetTypes()
                  where t.GetCustomAttributes<Command>().Count() > 0
                  select t;
     //run method where command.name = ping
}

The idea behind that being, to iterate through all available methods in the assembly, and then putting those into a List of some kind and then executing the method that has the command.name of what was passed in as an argument to the Handle function. When I get that to work, I of course will initilaize the methods list in the constructor of that class and not everytime call it when Handle is called, but for simplicity in my question I formulated my question independent of that, to have my example minimal. The question now is, how do I iterate through all methods in my assembly, and save those with the command attribute into a collection, and how do I run a method that has a certain value for the command.Name property? I'am kind of new to that whole reflection stuff, so if I did something else stupid or you have general tips on that topic please let me know!! Thanks in advance!!





Aucun commentaire:

Enregistrer un commentaire