Command-line-api: CommandResult missing ValueForOption<T>

Created on 8 Dec 2020  路  3Comments  路  Source: dotnet/command-line-api

CommandResult used to contain a ValueForOption method that could fetch values during validation, but that was removed by this commit.

Example code:

var command = new Command("someCommand", "Does something interesting")
{
    new Option<bool>(
        new [] {"--boolOption"},
        getDefaultValue: () => false,
        "Some bool option"),
    new Option<int>(
        new [] {"--intOption"},
        getDefaultValue: () => 1,
        "Some int option")
};

command.AddValidator(result =>
{
    try
    {
        var boolOptionValue= result.ValueForOption<bool>("boolOption");
        var intOptionValue = result.ValueForOption<int>("intOption");
        // This code ^ no longer compiles :-(

        if (!boolOptionValue && intOptionValue == 42)
        { return "You can't do that."; }
    }
#pragma warning disable RCS1075, CS0168
    catch (Exception e)
    {
        // Ignore exceptions here, any type issues will be caught elsewhere
    }
#pragma warning disable RCS1075, CS0168

    return null;
});

Is there a better way to achieve this or was the removal of the ValueForOption method an accident?

question

All 3 comments

I see the commit message stating:

Remove methods for getting values directly from a CommandResult. They should be accessed from the ParseResult, meaning code consuming the values isn't coupled to the structure of the CLI. This is important when a given option or argument might be added at multiple positions in the tree.

I'm using the CommandLineBuilder and I'm not sure how command validators are expected to be added in a way that they can validate multiple options against one another. In my example above the only invalid option is if both boolOption is true and intOption is 42.

Same problem. I'm using this approach for mutually inclusive / exclusive operations (as this approach was a workaround for this feature not being supported natively)

```C#
setCmd.AddValidator(commandResult =>
{
DirectoryInfo workspace = commandResult.ValueForOption("workspace-path");
DirectoryInfo publish = commandResult.ValueForOption("publish-path");
string username = commandResult.ValueForOption("username");
string key = commandResult.ValueForOption("key");
string value = commandResult.ValueForOption("value");

  if (workspace == null && publish == null && username == null && key == null && value == null)
  {
      return "Please specify at least one option.";
  }

  if ((key != null && value == null) || (key == null && value != null))
  {
      return "--key & --value are mutually inclusive. Please specify a value for --key AND --value";
  }

  return null;

});
```
Is there a better way of achieving this now?

You can do this using the ParseArgument<T> delegate accepted by the Argument<T> and Option<T> constructors.

image

Was this page helpful?
0 / 5 - 0 ratings