0

I would like to code a framework in C# Console Application(CLI), details aren't important. I don't know, how to recognize commands cleanly, and shortly. I tried with switch-case:

    public static void command_recognizing(string command) // random example
    {
        string[] tmp_array = command.Split(' ');
        switch(tmp_array[0])
        {
            case("help"):
                method_library.help(); // no need argument
                break;
            case("time"):
                method_library.time(); // no need argument
                break;
            case("shutdown"):
                method_library.shutdown(tmp_array); // need argument
                break;
            default:
                Console.WriteLine("Error! {0} is not a known command!",tmp_array[0]);
                break;
        }
    }

I also tried if-else:

     public static void command_recognizing(string command) // random example
    {
        string[] tmp_array = command.Split(' ');
        if(command.Contains("help"))
        {
            method_library.help(); // no need argument
        }
        else if(command.Contains("time"))
        {
            method_library.time(); // no need argument
        }
        else if(command.Contains("shutdown"))
        {
            method_library.shutdown(tmp_array); // need argument
        }
        else
        {
            Console.WriteLine("Error! {0} is not a known command!",tmp_array[0]);
        }
    }

I tried to store the commands in a string array, still the same, long and ugly.

There is any other way, to make the command recognizing shorter, cleaner and easier to modify? Foregive me for my english. Feel free to correct me!

Oteg
  • 3
  • 1

1 Answers1

1

You could use Reflection to execute methods of a class.

void Main() {
    var cmd = new Commands();

    while (!cmd.Exitting) {
        var cmdline = Console.ReadLine();
        var cmdargs = Regex.Split(cmdline.Trim(), @"\s+");
        if (!cmd.TryInvokeMember(cmdargs[0], cmdargs.Skip(1).ToArray()))
            Console.WriteLine($"Unknown command: {cmdargs[0]}");
    }
}

// Define other methods and classes here
public class Commands {
    public bool Exitting { get; private set; }

    public Commands() {
        Exitting = false;
    }

    public void exit() {
        Exitting = true;
    }

    public int sum(object[] args) {
        return args.Select(s => Convert.ToInt32(s)).Sum();
    }

    public bool TryInvokeMember(string methodName, object[] args) {
        var method = typeof(Commands).GetMethod(methodName.ToLower());

        if (method != null) {
            object res;
            if (method.GetParameters().Length > 0)
                res = method.Invoke(this, new object[] { args });
            else
                res = method.Invoke(this, new object[0]);

            if (method.ReturnType != typeof(void))
                Console.WriteLine(res.ToString());

            return true;
        }
        else
            return false;
    }
}
NetMage
  • 26,163
  • 3
  • 34
  • 55
  • NetMage you are awesome, I'm not able to write down, how big was your help. Exactly this is what I want. – Oteg May 25 '17 at 21:11
  • Thanks to you NetMage, my framework started growing, the core only has 3000 lines of code(Not Ready). if you didn't help, the core should be 4-5 thousand of line of code. – Oteg Jun 09 '17 at 20:16
  • While I mostly write my CLI programs in Perl (I write front ends to Cisco CLI to help my job), it has been a hobby to create CLIs for me. Glad it helped you. – NetMage Jun 09 '17 at 20:42