¿Es posible vincular directamente la entrada de la línea de comando a NodaTime.Duration (o System.TimeSpan ) usando System.CommandLine ? ¿Tal vez proporcionando un convertidor personalizado en alguna parte?
static void Main(string[] args) { var rootCommand = new RootCommand { new Option<Duration>("--my-duration"), }; rootCommand.Handler = CommandHandler.Create( (Duration myDuration) => { Console.WriteLine(myDuration); }); rootCommand.InvokeAsync(args); }No he trabajado mucho con System.CommandLine , y no hay mucha documentación sobre el análisis personalizado, pero creo que lo que quiere es un ParseArgument<T> . Afortunadamente, es bastante fácil escribir un método de extensión en NodaTime IPattern<T> para crear una instancia de eso.
Aquí hay un método de extensión no muy probado a fondo:
using NodaTime.Text; using System.CommandLine.Parsing; namespace Demo { public static class PatternExtensions { public static ParseArgument<T> ToParseArgument<T>(this IPattern<T> pattern) => result => ParseResult<T>(pattern, result); private static T ParseResult<T>(IPattern<T> pattern, ArgumentResult result) { // TODO: Check whether Tokens is actually what we want to use. if (result.Tokens.Count != 1) { result.ErrorMessage = "Only a single token can be parsed"; return default; } var token = result.Tokens[0]; var nodaResult = pattern.Parse(token.Value); if (nodaResult.Success) { return nodaResult.Value; } else { result.ErrorMessage = nodaResult.Exception.Message; return default; } } } }Y el código para usarlo:
using NodaTime; using NodaTime.Text; using System; using System.CommandLine; using System.CommandLine.Invocation; using Demo; // To make the extension method available class Program { static void Main(string[] args) { var rootCommand = new RootCommand { new Option<Duration>( "--my-duration", DurationPattern.JsonRoundtrip.ToParseArgument()), }; rootCommand.Handler = CommandHandler.Create( (Duration myDuration) => Console.WriteLine(myDuration)); rootCommand.Invoke(args); } } El patrón que se analiza ( DurationPattern.JsonRoundtrip ) usa "número de horas" como la parte más significativa, mientras que el formato predeterminado (usado por Console.WriteLine en este caso) usa "número de días", por lo que es fácil darse cuenta de que realmente está analizando:
$ dotnet run -- --my-duration=27:23:45 1:03:23:45