【问题标题】:How to retrieve the args array after using AddCommandLine使用 AddCommandLine 后如何检索 args 数组
【发布时间】:2020-01-23 09:33:03
【问题描述】:

我正在为控制台应用程序开发 POC,在设置中使用 AddCommandLine 后,我正在努力从配置中检索命令行值。

csproj

<PropertyGroup>
    <OutputType>Exe</OutputType>
    <TargetFramework>netcoreapp3.1</TargetFramework>
  </PropertyGroup>

程序类

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

ConsoleApp 类

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

foreach 循环之前的 Parser 部分无法编译,并且循环的输出不会打印出我添加的任何参数。

我知道一般建议是 var someValue = Configuration.GetValue&lt;int&gt;("MySetting:SomeValue"); 参数为 --MySetting=SomeValue 是检索 cmd 行值的推荐方法。

我用作参数的值是delete -e CI -t depchpolestar -l de-DE,当我查看我的配置对象时,我看到了

这就是我认为var t = config.GetSection("Args"); 应该检索args 数组的原因。我也尝试过var t = config.GetValue&lt;string[]&gt;("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);

执行命中 DoWork 方法。很好,但 DeleteOptions.cs 定义了一个动词,目的是添加更多命令。所以要做更多的工作,但要走正确的路。

[编辑] 我也意识到我不需要添加 AddCommandLine() 调用,因为它们是默认添加的。

【问题讨论】:

    标签: .net-core command-line-parser


    【解决方案1】:

    好吧,我似乎把这件事复杂化了,最后得到了这个:

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

    这是 ConsoleApp 中的运行方法:

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

    这可以让我将其用作交互式控制台应用程序。不过,我确实对 DI 有疑问。我创建了一个设置日志记录的 OptionsBase 类,并且我已经这样做了,因为尝试向任何 Options 类添加参数失败,说明无法找到无参数构造函数。所以我假设 CommandLine 需要默认构造函数才能工作。以我的方式获取记录器会给我多个日志文件,所以我需要修复它。

    【讨论】:

    • 仍然不确定您如何访问您在上面粘贴的代码中使用AddCommandLine 添加的args
    • 是的,现在阅读它我明白你的意思,但我无法再访问该代码,因此无法检查你。 ReadFromConsole() 似乎正在获取它们。它并不完美,我绝对没有解决我想要解决的所有问题。如果我不得不再次做类似的事情,我会回复一个更好的理解。
    猜你喜欢
    • 2021-07-02
    • 2014-03-12
    • 2021-09-21
    • 2020-08-27
    • 1970-01-01
    • 1970-01-01
    • 2020-11-11
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多