How to implement custom command line & execution

2019-02-27 17:00发布

问题:

I'm trying to build a custom commandline for my app, i have several basic commands, and i simply use bunch of "if" statements to check what the command is. currently it looks something like this

public void ExecuteCommand()
    {
        string input = ReadLine(); //gets last string from input
        bool isDone = false; //need bool to check whether command was executed or no, by default false.

        Match result = Regex.Match(input, @"([^\s]+)"); //to get command name
        string commandName = result.Value.ToLower();

        string value = Regex.Match(input, @"\s(.*)").Value; //to get its parameter. currently everything after ' ' space.

        if (commandName == "close")
        {
            Close(); isDone = true;
        }

        //so commandline is separate window, and appendedForm is a main form. in which some functions are executed.

        if (commandName == "exit")
        {
            appendedForm.Close();
        }

        if (commandName == "spoof")
        {
            appendedForm.Fn_Spoof();
            isDone = true;
        }

        if(commandName == "spoofstop")
        {
            appendedForm.Fn_StopCapture();
            isDone = true;
        }

        if(commandName == "scan")
        {
            appendedForm.Fn_Scan(); isDone = true;
        }

        if(commandName == "clear")
        {
            output.Text = "";
            WriteLine("Console cleared. Cache is empty.");
            //data_lines.Clear();

            isDone = true;

        }
        ...
}

So that's basically it. I have a mainForm, and commandline form. string input is typed into commandline, then I check the name of command and execute some function from mainForm.

My question is, what is the best way of implementing such kind of thing? I surely can just continue writing bunch of "if"s, but something tells me that it's not the best way to make it.

I've thought of creating class "Command"

 public class Command
 {
    public string name;
    public string description;
    public bool hasParameter;

    Command()
    {

    }
 }

And storing all commands in some sort of array, but I am not sure how would I use this to call a function from mainForm.

Any ideas are welcome!

回答1:

You could stuff all commands into a Dictionary<string, someDelegate>; if you can live with all commands having the same return type.

I have used string and set up a few commands.

I make use of the params keyword to avoid the ugly new object[] on each call.

You still need to cast the arguments, unless you can make them all one type. (Which may actually be not such a bad idea, as they all come from an input string..)

Here is an example:

public delegate string cmdDel(params object[] args);

Dictionary<string,  cmdDel> cmd = new Dictionary<string,  cmdDel>();

Add a few functions:

cmd.Add("clear", cmd_clear);
cmd.Add("exit", cmd_exit);
cmd.Add("add", cmd_add);
cmd.Add("log", cmd_log);

With these bodies:

public string cmd_clear(params object[] args)
{
    return "cleared";
}

public string cmd_exit(params object[] args)
{
    return "exit";
}

public string cmd_add(params object[] args)
{
    return ((int)args[0] + (int)args[1]).ToString();
}

public string cmd_log(params object[] args)
{
    StringBuilder log = new StringBuilder();
    foreach (object a in args) log.Append(a.ToString() + " ");
    return log.ToString(); 
}

And test:

Console.WriteLine(cmd["clear"]());
Console.WriteLine(cmd["add"]( 23, 42));
Console.WriteLine(cmd["log"]( 23, "+" + 42, "=", cmd["add"]( 23, 42) ));
Console.WriteLine(cmd["exit"]());

cleared

65

23 + 42 = 65

exit

Of course you still need to use (at least) as many lines for setup as you have commands. And also need to do a similar amount of error checking.

But the command processing part can get pretty simple.