dotnet / dotnet/command-line-api
Command validators don't seem to use the default value factory of an Option
- Lingua principale
- C#
- Stelle
- 3.7k
- Fork
- 428
- Metriche di merge delle PR
- Nessuna PR unita negli ultimi 30g
Descrizione
I've been on 2.0.0-beta4 for a while, and only recently gotten around to update to 2.0.10. One of the more interresting changes has been how validations work. It bugged me that I only had a single error message return and had to join multiple ones myself if there was more than one issue; but new API with `result.AddError` makes this a lot nicer.
However, I noticed that my old command-level validator didn't work anymore:
```c#
internal sealed class MySubCommand : Command
{
private readonly Option _multiplier = new("-m", "--multiplier") { Description = "Value multiplier, must be a positive non-zero value", DefaultValueFactory = _ => 1);
public MySubCommand() : base("mysub", "Babies first subcommand")
{
Add(_multiplier);
Validators.Add(result =>
{
if (result.GetValue(_multiplier) <= 0)
result.AddError("Multiplier must be greater than 0.");
});
SetAction(Handle);
}
public int Handle(ParseResult parseResult) { /* ... */ }
}
```
As it turns out, that would return 0 (the default value for `int`) rather than what `DefaultValueFactory` would give me.
The `-m` argument is generally optional; but when it's specified I need it to be positive/non-zero.
In my case though, the fix is simple: Put the validation on the option itself (which wasn't a thing before; or I just overlooked it):
```diff
- Validators.Add(result =>
+ _multiplier.Validators.Add(result =>
{
if (result.GetValue(_multiplier) <= 0)
result.AddError("Multiplier must be greater than 0.");
});
```
(Which could even go and use `result.GetValueOrDefault()` instead, since it's specific to the option that way.)
In 2.0.0-beta4, this was simply:
```c#
AddValidator(result =>
{
if (result.GetValueForOption(_multiplier) <= 0)
result.ErrorMessage = "Multiplier must be greater than 0.";
});
```
(Which felt straight-forward to migrate over, since there was no real mention of this behavior in the 2.0.0-beta5 migration guide. And the fact that I had to keep my own error list if I did more than one validation in there; but I omitted that for brevity.)
And that made me wonder: Since command-level validations are intended for cross-argument checks (like, if related arguments like ranges or from/to etc. are passed; whether they work in combination), wouldn't this potentially cause subtle bugs if someone expected the result to be as produced by the `DefaultValueFactory`? Is this the intended behavior of the command-level validator?
Guida per i contributori
Apri la guida per i contributori
Direzione di ricerca
Inizia tracciando come i Validators a livello di comando usano result.GetValue(_multiplier) e come viene applicato il DefaultValueFactory di un'Option. Confronta questo comportamento con i validatori a livello di opzione e con GetValueOrDefault(); in questo modo viene stabilita la gestione prevista delle opzioni omesse e la discrepanza osservata è coperta dal comportamento di convalida pertinente.
Scritto dal modello di indicizzazione a partire dal testo della issue.
Valutazione
- Stack tecnologico
- csharp
- Ambito
- cli
- Tipo di issue
- Bug
- Difficoltà
- 3/5
- Tempo stimato
- 1-2 giorni
- Stato di attività
- Tranquilla
- Chiarezza
- Abbastanza chiara
- Idoneità per principianti
- 52/100