如何使用System.CommandLine实现NodaTime.Duration的命令行参数绑定
问题解答
绑定支持说明
System.TimeSpan可以直接绑定:System.CommandLine内置了TimeSpan的类型转换逻辑,直接声明Option<TimeSpan>即可正常解析命令行输入,无需额外配置。NodaTime.Duration默认不支持直接绑定,但可以通过自定义转换逻辑实现需求。
实现NodaTime.Duration绑定的两种方案
方案1:针对单个Option指定解析逻辑
直接在定义Option<Duration>时传入parseArgument委托实现自定义解析,适合仅少数地方使用Duration参数的场景,示例代码如下:
using NodaTime; using System.CommandLine; using System.CommandLine.NamingConventionBinder; static void Main(string[] args) { // 定义带自定义解析逻辑的Duration参数 var durationOption = new Option<Duration>( name: "--my-duration", parseArgument: result => { string input = result.Tokens.Single().Value; // 可根据业务需求调整解析规则,比如支持"1h""30m"等简写格式 if (Duration.TryParse(input, out var validDuration)) { return validDuration; } // 解析失败时返回错误提示 result.ErrorMessage = $"输入值 {input} 无法转换为合法的Duration类型"; return default; }); var rootCommand = new RootCommand { durationOption }; rootCommand.Handler = CommandHandler.Create( (Duration myDuration) => { Console.WriteLine(myDuration); }); rootCommand.InvokeAsync(args).Wait(); }
方案2:注册全局类型转换器
如果项目中多处使用Duration作为命令行参数,可注册全局TypeConverter避免重复编写解析逻辑,步骤如下:
- 自定义Duration的TypeConverter
using System.ComponentModel; using NodaTime; public class DurationTypeConverter : TypeConverter { public override bool CanConvertFrom(ITypeDescriptorContext? context, Type sourceType) { return sourceType == typeof(string) || base.CanConvertFrom(context, sourceType); } public override object? ConvertFrom(ITypeDescriptorContext? context, System.Globalization.CultureInfo? culture, object value) { if (value is string input && Duration.TryParse(input, out var duration)) { return duration; } return base.ConvertFrom(context, culture, value); } }
- 程序启动时注册转换器,之后即可直接按原生方式声明
Option<Duration>
// 注册全局转换器 TypeDescriptor.AddAttributes(typeof(Duration), new TypeConverterAttribute(typeof(DurationTypeConverter))); // 后续可直接按原始代码写法使用 var rootCommand = new RootCommand { new Option<Duration>("--my-duration"), }; rootCommand.Handler = CommandHandler.Create( (Duration myDuration) => { Console.WriteLine(myDuration); }); rootCommand.InvokeAsync(args);
内容的提问来源于stack exchange,提问作者jack
相关产品推荐
相关产品推荐

