DazManCat
DazManCat

Reputation: 3630

Call a method in C# determined by a parameter

I have a list of methods I wish to call and a button accompaning each and a generic method to handle the buttons.

Using the commandArgument how can I run the selected method.

E.g. Click run method1 button. In handler for button click call the method as named in commandArgument

Upvotes: 2

Views: 593

Answers (4)

Dave Thieben
Dave Thieben

Reputation: 5437

I like Ian's answer, but if you want something less complex, you could just set up a dictionary of delegates:

private IDictionary<string, Action> actions = new Dictionary<string, Action> {
    { "MethodA", MethodA },
    { "MethodB", MethodB }
};

then

protected void Button_Command( object sender, CommandEventArgs e )
{
    if( actions.ContainsKey( e.CommandArgument ) )
        actions[e.CommandArgument]();
    else
        throw new ArgumentException( "Cannot find action for key: "+ e.CommandArgument );
}

of course, could be modified to accept arguments if you know their type. this assumes MethodA and MethodB have no arguments and return void.

Upvotes: 1

Ian Johnson
Ian Johnson

Reputation: 2254

Why not actually use something like this command pattern?

public interface ICommand
{
   bool CanExecute(string command);
   void Execute();
}

public class MethodACommand : ICommand
{
    private MyForm form;
    public MethodACommand(MyForm form) {... }

    public bool CanExecute(string command) { return command.Equals("MethodA"); }
    public void Execute() { form.MethodA(); }
}

public class CommandHandler
{
    public CommandHandler(IEnumerable<ICommand> commandString) {...}
    public Execute(string command) 
    {
        foreach(var command in Commands)
        {
             if (command.CanExecute(commandString))
             {
                 command.Execute();
                 break;
             }
        }
    }
}

protected void Button_Click(object sender, EventArgs e)
{
    string arg = ((Button)sender).CommandArgument;  // = MethodA
    commandHandler.Execute(arg);
}

Upvotes: 3

djdd87
djdd87

Reputation: 68506

So the string in the CommandArgument matches the name of a method? If you must do this then you could use reflection. I'm assuming you've basically got a single button click event for each button or you wouldn't be asking this:

private void MethodA() { }

protected void Button_Click(object sender, EventArgs e)
{
    string arg = ((Button)sender).CommandArgument;  // = MethodA
    MethodInfo method = this.GetType().GetMethod(arg);
    method.Invoke(this, null);
}

Although this looks like a massive code smell. Why do you have to do it this way? Why can you not just give each button a separate event handler and call each method directly?

Alternatively, why not use a switch statement on the argument:

protected void Button_Click(object sender, EventArgs e)
{
    string arg = ((Button)sender).CommandArgument;  // = MethodA
    switch (arg)
    {
        case "MethodA":
            MethodA(); break;
        case "MethodB":
            MethodB(); break;
    }
}

Upvotes: 1

Grzenio
Grzenio

Reputation: 36679

If you know all the methods that are to be called and the number is not very large I would just use a switch statement to call them. Otherwise you have to use reflection, see e.g. http://www.codeproject.com/KB/cs/CallMethodNameInString.aspx for some examples.

Upvotes: 1

Related Questions