A simple pattern for using System.CommandLine with dependency injection
I've recently started using the new System.CommandLine
packages when building CLI tools. I think they're a really useful addition to the C# libraries, but there isn't a huge amount of documentation out there about how best to use them so I thought I'd share some of the patterns we've been building up.
So, first we install the NuGet package. Remember to turn "show pre-release" on as the package is still in beta!
We then start by creating a command:
This defines a single option, called name
which will be passed into the tool. It also takes an Options
class as a constructor argument, which we want to retrieve from the app settings and pass in via DI. The command then uses the greeting from the app settings, and the name which has been passed in to display a greeting.
So, in order to set up the dependency injection we use an extension method on the service provider:
This will retrieve anything that implements Command
which is defined in the same namespace as the GreetCommand
, and add it to the service collection. In order to cover commands in other namespaces/assemblies this would need to be updated.
We then write our (fairly simple!) main body of the program:
And add the necessary app setting to the appsettings.json
file (remembering to set it to "copy if newer" to the output directory):
{
"greet:Greeting": "Hello"
}
If we then go to the properties for our project, and use
greet --name "Carmel"
as the debug arguments, then the output will be:
Hello Carmel!
And there we have it! A simple pattern for using dependency injection with System.CommandLine
. Of course, these packages are still prerelease so things might change, and hopefully in future there will be more in-built support for these patterns. But for now, hope this helps!
If you want to see how the tool all fits together, here's the GitHub repo!