如何使用 System.CommandLine 绑定 NodaTime.Duration?

Posted

技术标签:

【中文标题】如何使用 System.CommandLine 绑定 NodaTime.Duration?【英文标题】:How to bind NodaTime.Duration using System.CommandLine? 【发布时间】:2021-10-16 12:08:47 【问题描述】:

是否可以使用System.CommandLine 直接将命令行输入绑定到NodaTime.Duration(或System.TimeSpan)?也许通过在某处提供自定义转换器?

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);

【问题讨论】:

【参考方案1】:

我与System.CommandLine 的合作不多,关于自定义解析的文档也不多,但我相信您想要的是ParseArgument&lt;T&gt;。幸运的是,在 NodaTime IPattern&lt;T&gt; 上编写扩展方法来创建它的实例相当容易。

这是一个未经彻底测试的扩展方法:

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;
            
        
    

以及使用它的代码:

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);
    

被解析的模式 (DurationPattern.JsonRoundtrip) 使用“小时数”作为最重要的部分,而默认格式(在这种情况下由 Console.WriteLine 使用)使用“天数”,因此很容易判断它确实在解析:

$ dotnet run -- --my-duration=27:23:45
1:03:23:45

【讨论】:

以上是关于如何使用 System.CommandLine 绑定 NodaTime.Duration?的主要内容,如果未能解决你的问题,请参考以下文章

System.CommandLine选项Option

System.CommandLine版CSRebot

看看《System.CommandLine》

System.CommandLine参数Argument

通过System.CommandLine快速生成支持命令行的应用

如何使用 WPF 按钮的参数或绑定来更改 XAML 样式中的 fa 图标