one*_*rth 6 command-line-parser .net-core
我正在为控制台应用程序开发 POC,在设置中使用 AddCommandLine 后,我正在努力从配置中检索命令行值。
工程项目
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>netcoreapp3.1</TargetFramework>
</PropertyGroup>
Run Code Online (Sandbox Code Playgroud)
节目类
public static class Program
{
public static async Task Main(string[] args)
{
Log.Logger = new LoggerConfiguration()
.Enrich.FromLogContext()
.WriteTo.Console()
.WriteTo.RollingFile("Logs//log.txt")
.CreateLogger();
await CreateHostBuilder(args)
.Build()
.RunAsync();
}
public static IHostBuilder CreateHostBuilder(string[] args) =>
Host.CreateDefaultBuilder(args)
.UseSerilog()
.ConfigureAppConfiguration((hostingContext, config) =>
{
config.AddJsonFile("settings.json", true, true);
config.AddCommandLine(args);
})
.ConfigureServices((hostcontext, services) =>
{
services.AddHostedService<ConsoleApp>();
});
}
Run Code Online (Sandbox Code Playgroud)
控制台应用程序类
public class ConsoleApp : IHostedService
{
private readonly IConfiguration config;
private readonly ILogger<ConsoleApp> log;
public ConsoleApp(IConfiguration configuration, ILogger<ConsoleApp> logger)
{
config = configuration;
log = logger;
}
public Task StartAsync(CancellationToken cancellationToken)
{
var t = config.GetSection("Args");
Parser.Default.ParseArguments<DeleteOptions>(t)
.WithParsed<DeleteOptions>()
.WithNotParsed();
foreach (var c in config.AsEnumerable())
{
log.LogInformation($"{c.Key, -15}:{c.Value}");
}
log.LogInformation($"Completing Start Task");
return Task.CompletedTask;
}
public Task StopAsync(CancellationToken cancellationToken)
{
log.LogInformation($"Complete End Task");
return Task.CompletedTask;
}
}
Run Code Online (Sandbox Code Playgroud)
foreach 循环之前的解析器部分不会编译,循环的输出不会打印出我添加的任何参数。
我知道一般建议是var someValue = Configuration.GetValue<int>("MySetting:SomeValue");参数所在的位置--MySetting=SomeValue是检索命令行值的推荐方法。
我用作参数的值是delete -e CI -t depchpolestar -l de-DE,当我查看我的配置对象时,我看到
这就是为什么我认为该行var t = config.GetSection("Args");应该检索 args 数组。我也尝试过var t = config.GetValue<string[]>("Args");,但似乎都不起作用。在我看来,配置对象的索引 4 是一个以“Args”为键的字符串数组
如何检索字符串数组以便将其传递到 CommandLineParser 的 ParseArguments 方法中?
[编辑]一种解决方案:
我现在可以传递参数,但这不是一个特别好的方法;如果我将参数构造为--delete "-e CI -t depchpolestar -l de-DE"而不是delete -e CI -t depchpolestar -l de-DE将以下代码添加到 ConsoleApp 类中:
var args = config.GetValue<string>("delete");
string[] arguments = null;
if(!string.IsNullOrEmpty(args))
{
var tempArgs = args.Split(" ");
arguments = new string[tempArgs.Length + 1];
arguments[0] = "delete";
for(int i = 0; i < tempArgs.Length; ++i)
{
arguments[i + 1] = tempArgs[i];
}
}
Parser.Default.ParseArguments<DeleteOptions>(arguments)
.WithParsed<DeleteOptions>(async c => await c.Dowork())
.WithNotParsed(HandleParseError);
Run Code Online (Sandbox Code Playgroud)
执行命中 DoWork 方法。很好,但DeleteOptions.cs 定义了一个动词,其目的是添加更多命令。所以还有更多的工作要做,但要走正确的路。
[编辑]我还意识到我不需要添加调用,AddCommandLine()因为它们是默认添加的。
好吧,看来我把这个复杂化了,最终得到了这个:
public static class Program
{
public static async Task Main(string[] args)
{
var builtHost = CreateHostBuilder(args).Build();
var console = builtHost.Services.GetService<ConsoleApp>();
await console.Run();
}
public static IHostBuilder CreateHostBuilder(string[] args) =>
Host.CreateDefaultBuilder(args)
.UseSerilog()
.ConfigureAppConfiguration((hostingContext, config) =>
{
config.AddJsonFile("settings.json", true, true);
config.AddCommandLine(args);
})
.ConfigureServices((hostcontext, services) =>
{
services.AddTransient<ConsoleApp>();
});
}
Run Code Online (Sandbox Code Playgroud)
这是 ConsoleApp 中的 run 方法:
public Task Run()
{
while (true)
{
var input = ReadFromConsole();
if (string.IsNullOrWhiteSpace(input))
{
continue;
}
else if (input.ToLower().Equals("exit"))
{
break;
}
else
{
Parser.Default.ParseArguments<DeleteOptions, ConcatOptions, DownloadOptions, ReportOptions>(input.Split(" "))
.WithParsed<DeleteOptions>(async options => await options.DoWork())
.WithParsed<ConcatOptions>(async options => await options.DoWork())
.WithParsed<DownloadOptions>(async options => await options.DoWork())
.WithParsed<ReportOptions>(async options => await options.DoWork())
.WithNotParsed(HandleParseError);
}
}
return Task.CompletedTask;
}
Run Code Online (Sandbox Code Playgroud)
这非常适合我将其用作交互式控制台应用程序。不过我的 DI 确实有问题。我创建了一个设置日志记录的 OptionsBase 类,并且我这样做是因为尝试向任何选项类添加参数失败,说明无法找到无参数构造函数。所以我假设 CommandLine 需要默认构造函数才能工作。按照我的方式获取记录器会给我多个日志文件,所以我需要解决这个问题。
| 归档时间: |
|
| 查看次数: |
3483 次 |
| 最近记录: |