Not the last console application. GoCommando

 
event

The first one in this series is GoCommando.
As it needs to be in order to be considered, comes as a NuGet package and it praises itself to be small and with a mixture of interfaces and attributes.

Command-centered

A command implements ICommand, gets its command-line metadata from attributes (CommandAttribute and DescriptionAttribute).

Properties of the command become command line parameters if decorated with ParameterAttribute and all possible features of the parameter (long name, short name, optionality, default value) are provided via constructor with default values.

Implementing our example

The implementation of our commands is pretty straightforward:

Just translate the properties of the ICommand to the argument object and call the wrapped command.
If the framework was embraced completely, we would implement our commands directly.

The Challenges

Mandatory Arguments

Mandatory arguments are the default and optional arguments is a matter of changing the value: [Parameter("awesome", "a", optional: true)].

Reporting a missing mandatory argument just works:

Any extra, non-mapped arguments will also throw an exception, which is nice, unless that behavior in unwanted.

Non-Textual arguments

Declaring the right type for the property takes one very far and flags (boolean properties) are supported OOTB.
Failures, however, are not handled gracefully and the exception flows:

Default values are provided as strings, so expect the same conversion rules.

Multi-arguments

As one can see from the implementation of the locations parameter of somethin-else, such property is not a collection, but a string property that needs to be parsed into a collection of strings. Unfortunately, out-of-the-box values are converted using Convert.ChangeTpe() which is very limited and does not support collections and there is no way to inject some custom behavior.
It is not a deal breaker but is something to keep in mind. Fortunately, we can help our users by providing examples of valid values:

Showing Help

Running the program without arguments provides a nice overview:

Which can be extended to the command level by using the -help command argument:

Being an attribute-driven framework, localization becomes a challenge and there is nothing I could see to help us with that. Code is simple enough and well-factored to send a pull request to support resource files and string keys, the same way we can do in other attribute-driven frameworks, such as MVC.

Command dispatching

The concept of a command is The central concept of the library, so it fits nicely into our example.
On the other hand, if what we have is single command utility, sticking the sole command after the executable might be confusing.
There is an open issue so it is not far-fetched to assume that a default, single command feature will be added.

Invoking the command is a matter of calling Go.Run() from your console program entry point.

One nice and not widely announced feature is that it provides a way to hook up your IOC container to create command instances, by implementing the ICommandFactory interface.
In our sample, I just did an extremly poor man's DI, but plugging in your favorite container is a breeze:

When using command factories, one just specifies the type with the generic call Go.Run<CustomFactory>();.

Conclusion

GoCommando it is indeed small, useful and focused. The code is extremely well structured and the help is about right (bringing the extra features such as command factories from code samples into the wiki would cherry-top the package).

Definitely worth considering for simple (and not so simple) scenarios.

Last Console Series

  1. The beginning
  2. GoCommando (this)
  3. Command Line Parser
  4. PowerArgs
  5. LBi.Cli.Arguments
  6. Command Line Utils
  7. CLAP
  8. Wrap-up