开发者

Call a method in C# determined by a parameter

开发者 https://www.devze.com 2023-01-13 08:13 出处:网络
I have a list of methods I wish to call and a button accompaning each and a generic method to handle the buttons.

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 selec开发者_如何学JAVAted method.

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


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);
}


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;
    }
}


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.


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.

0

精彩评论

暂无评论...
验证码 换一张
取 消