2010-08-24 44 views
2

我有一个我希望调用的方法列表和一个按钮,它们支持每个方法以及处理按钮的一般方法。在C#中调用一个由参数确定的方法

使用commandArgument如何运行选定的方法。

E.g.点击run method1按钮。在按钮点击处理程序中调用方法如commandArgument所示

+0

你真的应该考虑改变你的程序模式使用委托的方法 - 这是可能的滥用,特别是当使用字符串作为参数.. – 2010-08-24 11:06:34

+0

argh ...为asp.net设置标签,并撤销我的回答。 – 2010-08-24 12:31:30

回答

1

因此,CommandArgument中的字符串与方法的名称匹配?如果你必须这样做,那么你可以使用反射。我假设你已经基本上得到了每个按钮一个按钮点击事件,或者你就不会问这样的:

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

虽然这看起来像一个巨大的代码味道。你为什么要这样做?为什么你不能只给每个按钮一个单独的事件处理程序并直接调用每个方法?

或者,为什么不能在参数中使用switch语句:

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

啊......这很慢并且很危险......更好的做法是使用代表。 – 2010-08-24 11:04:46

1

如果您知道所有要调用的方法并且该数字不是很大,那么我只需使用switch语句来调用它们。否则,你必须使用反射,参见例如http://www.codeproject.com/KB/cs/CallMethodNameInString.aspx的一些例子。

+0

我知道,但我想让列表成长。 我暂时只是使用switch case语句来设置它 – DazManCat 2010-08-24 14:41:16

3

为什么不实际使用这样的命令模式?

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

您不妨使用Button.Command事件而不是Button.Click事件。你会得到一个包含CommandName和CommandArgument的CommandEventArgs参数,所以你不需要从Button本身抓取它们。 (http://msdn.microsoft.com/en-us/library/system.web.ui.webcontrols.button.command.aspx) – 2010-08-24 14:00:33

+0

你是正确的使用命令事件,我很快打字并修改了按钮从以前的答案中点击调用代码 – 2010-08-24 16:00:26

1

我喜欢伊恩的答案,但如果你想要的东西那么复杂,你可以只设立代表的字典:

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

然后

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

,可能是如果你知道它们的类型,修改它以接受参数。这假定MethodA和MethodB没有参数并返回void。

相关问题