Search code examples
c#.netsystem.commandline

Console System.CommandLine command one liner with options?


I have a .net console app where I'm trying to make the code more concise. Currently to setup a command using System.CommandLine I have something like this:

using System.CommandLine;

var rootCommand = new RootCommand("CLI");

var theOption = new Option<int?>("--id", "Database ID");

var theCommand = new Command("stuff", "Do Stuff.") { theOption };

ret.SetHandler((id) =>
{
   Console.WriteLine($"Do stuff on id: {id}");
}, theOption);

rootCommand.Add(theCommand);

return rootCommand.Invoke(args);

What I'd like to do is make a one liner, but I'm not sure how to do so since I'm using the variable theOption twice. How could I do this? Looking for something like:

using System.CommandLine;

var rootCommand = new RootCommand("CLI");

//refactor theOption into below statement
var theOption = new Option<int?>("--id", "Database ID");

rootCommand.Add(
   new Command("stuff", "Do Stuff.") { theOption }
).SetHandler((id) =>
{
   Console.WriteLine($"Do stuff on id: {id}");
}, theOption);

return rootCommand.Invoke(args);

Any recommendations would be appreciated. My OCD is acting up without the indentation.


Solution

  • Without any knowledge of System.CommandLine, wouldn't you be able to achieve this with a simple extension method?

    public static RootCommand Add(this RootCommand root, Command command)
    {
        root.AddCommand(command);
    
        return root;
    }
    

    Something like this maybe? and of course whichever other extensibility you want to add, if you wanna make something neat for combining the command and handler, maybe something like this:

    public static RootCommand Configure(
        this RootCommand root, 
        Action<int?> handlerAction,
        Option<int?> handlerOption, 
        params Command[] commands)
    {
        root.SetHandler(handlerAction, handlerOption);
    
        for (int i = 0; i < commands.Length; i++)
        {
            root.AddCommand(commands[i]);
        }
    
        return root;
    }
    

    That should shorten it to:

    rootCommand.Configure((id) => { Console.WriteLine($"Do stuff on id: {id}"); }, theOption, theCommand, theCommand2);
    

    With however many commands you want, you can also reuse the options for all the commands within the extension method or whatnot, the world is your oyster and all that.