除了直接预处理 args 之外,还有什么方法可以确定是否提供了 NOT 选项(同时仍然允许默认值),以便有可能从 app.config 中读取
这是我想为其创建后备的示例选项:
static async Task<Int32> Main(String[] args) {
Option<Int32> pollingRateOption = new Option<Int32>(
aliases: new[] { "-r", "--Polling-Rate" },
description: "Rate at which to poll, in milliseconds.",
isDefault: true,
parseArgument: result => {
if (Int32.TryParse(result.Tokens.Single().Value, out Int32 pr)) {
if (pr < 1 || pr > 1000) {
result.ErrorMessage = "Polling-Rate must be an integer from 1-1000";
}
return pr;
} else {
result.ErrorMessage = "Polling-Rate must be an integer from 1-1000";
return 0; // Ignored.
}
}
);
pollingRateOption.ArgumentHelpName = "1-1000";
pollingRateOption.Arity = ArgumentArity.ExactlyOne;
pollingRateOption.SetDefaultValue(5);
RootCommand rootCommand = new RootCommand($"{AppName}");
rootCommand.AddOption(pollingRateOption);
rootCommand.SetHandler((pollingRateValue) => { Run(pollingRateValue); }, pollingRateOption);
return await rootCommand.InvokeAsync(args);
}
好吧,虽然这看起来有点hacky,但解决方案似乎是删除 SetDefaultValue(),保留 isDefault: true,然后使用 if (!result.Tokens.任意()).
不过,这有一个警告,在 parseArgument 处理程序中设置的任何值都将在 --help 文本中显示为默认值。因此,如果从 app.config 动态提取它, [default: ] 将是可变的。这可能是不可取的。
解决这个问题的方法似乎是使用 CommandLineBuilder() 覆盖帮助文本,并通过 .UseHelp() 硬编码默认文本。以下是最终解决方案的工作示例。
static async Task<Int32> Main(String[] args) {
Option<Int32> pollingRateOption = new Option<Int32>(
aliases: new[] { "-r", "--Polling-Rate" },
//description: "Rate at which to poll, in milliseconds.", //No longer needed, added through .UseHelp() below
isDefault: true,
parseArgument: result => {
Int32 pr;
if (!result.Tokens.Any()) { //If commandline option not specified, attempt to get it from app.config
if (!Int32.TryParse(ConfigurationManager.AppSettings["Polling-Rate"], out pr)) {
pr = 5; //Actual default if no option on commandline or in app.config
}
} else {
if (!Int32.TryParse(result.Tokens.Single().Value, out pr)) {
result.ErrorMessage = "Polling-Rate must be an integer from 1-1000";
}
}
if (pr < 1 || pr > 1000) {
result.ErrorMessage = "Polling-Rate must be an integer from 1-1000";
}
return pr;
}
);
pollingRateOption.ArgumentHelpName = "1-1000";
pollingRateOption.Arity = ArgumentArity.ExactlyOne;
//pollingRateOption.SetDefaultValue(5); //parseArgument handler will not fire on missing option if default is set
RootCommand rootCommand = new RootCommand($"{AppName}");
rootCommand.AddOption(pollingRateOption);
rootCommand.SetHandler((pollingRateValue) => { Run(pollingRateValue); }, pollingRateOption);
Parser parser = new CommandLineBuilder(rootCommand)
.UseDefaults()
.UseHelp(ctx => {
ctx.HelpBuilder.CustomizeSymbol(pollingRateOption, secondColumnText: "Rate at which to poll, in milliseconds. [default: 5]");
})
.Build();
return await parser.InvokeAsync(args);
}