top of page

.NET Console Applications — With Dragonfruit!



A typical .NET console application Mainmethod/ entry point looks like this

static void Main(string[] args)
{
    // ...
}

Arguments are represented as string values that the developer has to deal with.


So you end up having to either —


A — Make up a custom input format and write code to validate, parse and convert parameters and maybe if we can be bothered conform to windows or POSIX standard for command line syntax

OR


B — Ignore the arguments, and either hard code any possible inputs to your application or read them from a config file — which is what I usually ended up doing.


The issue with doing option A is that the code to parse the arguments could easily quite complex and you end up with more code for the parsing than for the what your little utility function was supposed to.

Wouldn’t it be great if we could just get this done easily?


Yes, we can now, with the help of DragonFruit!


Dragonfruit is a .NET package that allows you to specify strongly typed parameters in your Main method that can be then used as command-line arguments.

To see what it means, consider the following Main method in a console application.

class Program
{
    /// <summary>
    /// Utility to add Employee details.
    /// </summary>
    /// <param name="firstName">First name for Employee</param>
    /// <param name="lastName">Last name for Employee</param>
    /// <param name="dateOfBirth">Date of birth</param>
    /// <param name="address">Address array</param>
    /// <param name="employeeId">Employee Id</param>
    /// <param name="employeePhoto">Path to an image file</param>    static void Main(string firstName,
                        string lastName,
                        DateTime dateOfBirth,
                        string[] address = null,
                        int employeeId = 42,
                        FileInfo employeePhoto = null)
    {
        Console.WriteLine(@$"Employee details - 
                                Name : { firstName} { lastName}
                                DOB: { dateOfBirth }
                                Address: {string.Join(',', address  
                                          ?? Array.Empty<string>())}
                                Id: { employeeId }
                                Photo: { employeePhoto } 
                            ");
    }
}

All you need to do to supply arguments is to call the main program with the arguments and DragonFruit will do the rest.


So now we can call the application with POSIX style command parameters like so -

PS C:\> .\AddEmployee.exe --first-name=John --last-name=Doe --dateirth=31-jan-1984 --address="314 Pi Street" "Geometry Lane" "ABC314" --employee-id=145 --employee-photo="c:\pi.jpg"

and the output is

Employee details -
         Name : John Doe
         DOB: 31/04/1984 00:00:00
         Address: 314 Pi Street,Geometry Lane,ABC314
         Id: 145
         Photo: c:\pi.jpg

Notice that the arguments have been converted to the correct data type, it even managed to the parse the string array for address


In fact, DragonFruit does quite a bit more.

  • It generates the help documentation as well. It’s clever enough to use the documentation provided in the params help tags.

PS C:\> .\AddEmployee.exe --help

AddEmployee:
  Utility to add Employee details.

Usage:
  AddEmployee [options]

Options:
  --first-name <first-name>            First name for Employee
  --last-name <last-name>              Last name for Employee
  --date-of-birth <date-of-birth>      Date of birth
  --address <address>                  Address array [default: ]
  --employee-id <employee-id>          Employee Id [default: 0]
  --employee-photo <employee-photo>    Path to an image file [default: ]
  --version                            Show version information
  -?, -h, --help                       Show help and usage information
  • You get some basic validations out of the box

PS C:\> AddEmployee.exe --date-of-birth=incorrect-date-of-birthCannot parse argument 'incorrect-date-of-birth' for option '--date-of-birth' as expected type System.DateTime.
  • If you don’t specify the value of an argument, the default value of the parameter is used. e.g, in the following code, note that the Id is set to 42 by default, all other arguments are set to the default for the type.

PS C:\> .\AddEmployee.exe
Employee details -
         Name :
         DOB: 01/01/0001 00:00:00
         Address:
         Id: 42
         Photo:

In order to invoke this magic, you need to import the nuget package System.CommandLine.DragonFruit

Note: The package is still experimental, so you will need to include prerelease when you add the package.

That’s pretty much all there is to it. There are a few things to note though.


Caveats

  • The command argument syntax is POSIX style, you cannot customise argument names.

  • There is no way to use sub commands in arguments, so something like this can’t work.

AddEmployee.exe update --first-name John
  • There appears to be no way of marking arguments as required or mandatory.


Alternatives

Although DragonFruit is good enough for quite a few use cases and offers the easiest way to parse command line arguments, there may be times when you need to use something a bit more fully featured. There are a few options here -

  • System.CommandLine

This is the Core API that underlies DragonFruit.

  • CommandLineUtils

Nate McMaster’s CommandLineUtils is a pretty good one. It’s a fork off the same Microsoft.Extensions.CommandLineUtils that the System.CommandLine is forked from.

  • and a few others like the Mono.Options library.



Source: Medium


The Tech Platform

0 comments
bottom of page