c# - 如何使用System.CommandLine绑定(bind)NodaTime.Duration?

标签 c# .net command-line console-application nodatime

是否可以使用System.CommandLine直接将命令行输入绑定(bind)到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);
}

最佳答案

我没有与 System.CommandLine 合作过很多,并且关于自定义解析的文档并不多,但我相信您想要的是 ParseArgument<T> 。幸运的是,在 NodaTime 上编写扩展方法相当容易 IPattern<T>创建一个实例。

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

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

关于c# - 如何使用System.CommandLine绑定(bind)NodaTime.Duration?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/69595448/

相关文章:

c# - .NET 脚本编辑器的替代品

c# - 统一容器 : Register two singletones which implement two interfaces one of which is common

command-line - Websphere Application Server 6.1(本地化): Override locale for console messages

c# - 如何在 ASP.NET ApiController 中捕获 g-recaptcha-response?

c# - 如何在WPF中高效的展示图形?

c# - 应如何在 IHostedService 中使用取消标记?

c# - 如何在错误 JSON 的反序列化过程中忽略异常?

c# - NCron 默认记录器写入事件日志,抛出 SecurityException

C# 控制台应用程序使用命令行,命令不执行

bash - 如何使用循环保存所有 key 保管库 secret