Description
I want to fill the default values from some of my options from configuration stack. Since when using UseHost()
the Host
instance is built within the middleware, my Command
classes have no access to the Host
and it's configuration stack while defining options.
This is related to #1058 and #826.
I tried to extract this functionality into another middleware (calling RootCommand.Configure()), but the default values are determined before my middleware gets in action, so the value of option1
is still "abc"
and not affected by settings.json.
static void Main(string[] args)
{
var rootCommand = new RootCommand();
var commandLineParser =
new CommandLineBuilder(rootCommand)
.UseHost(hostBuilder =>
hostBuilder.ConfigureAppConfiguration(builder =>
{
builder.SetBasePath(Directory.GetCurrentDirectory())
.AddJsonFile("settings.json", true, true)
.AddEnvironmentVariables();
}))
.UseMiddleware(context => { rootCommand.Configure(context); })
.UseDefaults()
.Build();
commandLineParser.Invoke(args);
}
public class RootCommand : System.CommandLine.RootCommand
{
public RootCommand()
{
Add(Option1);
Handler = CommandHandler.Create<string, IHost>(Handle);
}
public Option<string> Option1 { get; } = new("--option1", () => "abc", "first option");
public void Configure(InvocationContext context)
{
Option1.SetDefaultValueFactory(() => context.GetHost().Services.GetRequiredService<IConfiguration>().GetValue<string>("DefaultOption1"));
}
public void Handle(string option1, IHost host)
{
Console.WriteLine(option1);
}
}
A nice solution were to allow somehow DI in the constructor of my RootCommand
.
For now the only solution I have is to bypass UseHost()
and create a host myself, passing it to the RootCommand
constructor and simply adding the Host
to Commandlines DI system. Alternatively just saving a reference to the host in a field and ignoring Commandline totally from the view of the Host
. But both lack of some functionality of UseHost()
like config directives and InvocationLifetime
.
static void Main(string[] args)
{
var host = new HostBuilder()
.ConfigureAppConfiguration(builder =>
{
builder.SetBasePath(Directory.GetCurrentDirectory())
.AddJsonFile("settings.json", true, true)
.AddEnvironmentVariables();
})
.Build();
var rootCommand = new RootCommand(host);
var commandLineParser =
new CommandLineBuilder(rootCommand)
.UseMiddleware(context => { context.BindingContext.AddService<IHost>(_ => host); })
.UseDefaults()
.Build();
commandLineParser.Invoke(args);
}
public class RootCommand : System.CommandLine.RootCommand
{
public RootCommand(IHost host)
{
Add(Option1);
Option1.SetDefaultValueFactory(() => host.Services.GetRequiredService<IConfiguration>().GetValue<string>("DefaultOption1"));
Handler = CommandHandler.Create<string, IHost>(Handle);
}
public Option<string> Option1 { get; } = new("--option1", () => "abc", "first option");
public void Handle(string option1, IHost host)
{
Console.WriteLine(option1);
}
}