未提供 System.CommandLine 选项时回退到 app.config 的最佳方法?

问题描述 投票:0回答:1

除了直接预处理 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);
}
app-config .net-4.8 system.commandline
1个回答
0
投票

好吧,虽然这看起来有点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);
}
© www.soinside.com 2019 - 2024. All rights reserved.