【问题标题】:Pass command-line arguments to Startup class in ASP.NET Core将命令行参数传递给 ASP.NET Core 中的 Startup 类
【发布时间】:2017-07-20 16:05:20
【问题描述】:

我有通过命令行传入的参数

private static int Main(string[] args)
{
    const string PORT = "12345"    ;

    var listeningUrl = $"http://localhost:{PORT}";

    var builder = new WebHostBuilder()
        .UseStartup<Startup>()
        .UseKestrel()
        .UseUrls(listeningUrl);

    var host = builder.Build();
    WriteLine($"Running on {PORT}");
    host.Run();

    return 0;
}

其中一个参数是日志输出目录。如何将此值放入我的 Startup 类中,以便在收到请求时将其写入此目录?

我想避免使用静态类。提供价值的服务会是正确的方式吗?如果是这样,我如何将服务注入到我的中间件中?

【问题讨论】:

    标签: asp.net .net asp.net-core owin katana


    【解决方案1】:

    您应该可以使用AddCommandLine() 扩展名。首先安装 Nuget 包Microsoft.Extensions.Configuration.CommandLine 并确保您有正确的导入:

    using Microsoft.Extensions.Configuration;
    

    现在更新您的 Main 方法以包含新配置:

    var config = new ConfigurationBuilder()
        .AddJsonFile("hosting.json", optional: true) //this is not needed, but could be useful
        .AddCommandLine(args)
        .Build();
    
    var builder = new WebHostBuilder()
        .UseConfiguration(config)  //<-- Add this
        .UseStartup<Startup>()
        .UseKestrel()
        .UseUrls(listeningUrl);
    

    现在您将命令行选项视为配置:

    dotnet run /MySetting:SomeValue=123
    

    并读入代码:

    var someValue = Configuration.GetValue<int>("MySetting:SomeValue");
    

    【讨论】:

    • 太棒了!你知道它存在于哪个 Nuget 包中吗?
    • 是的,听起来很合理,但它不在那里。
    • 我知道了,顶部有一个using Microsoft.Extensions.Configuration.CommandLine;,但仍然没有AddCommandLine 方法。
    • 包经理声称它是1.1.2: Successfully installed 'Microsoft.Extensions.Configuration.CommandLine 1.1.2'
    • 我其实两者都有。
    【解决方案2】:

    Dotnet Core 2

    您不需要 dotnet core 1.0 中的大部分代码来实现这一点。 AddCommandLinearguments 会在您使用以下语法构建WebHost 时自动注入

    第 1 步。

    public static IWebHost BuildWebHost(string[] args)
    {
        return WebHost.CreateDefaultBuilder(args)
                      .UseStartup<Startup>()
                      .Build();
    }
    

    步骤 2. 使用以下代码使用 DI 将配置注入 Startup.cs

    public class Startup
    {
        private readonly IConfiguration Configuration;
    
        public Startup(IConfiguration configuration)
        {
            Configuration = configuration;
        }
    
        ...
    
    }
    

    第 3 步。使用配置对象访问您的参数。

    var seed = Configuration.GetValue<bool>("seed");
    Console.WriteLine($"seed: {seed}");
    

    步骤 4. 使用参数启动应用程序

    dotnet run seed=True
    

    【讨论】:

      【解决方案3】:

      ASP.NET Core 2 答案:

      将默认 Program.cs 更改为:

      using System;
      using System.IO;
      using Microsoft.AspNetCore;
      using Microsoft.AspNetCore.Hosting;
      using Microsoft.Extensions.Configuration;
      
      public class Program
      {
          public static void Main(string[] args)
          {
              BuildWebHost(args).Run();
          }
      
          public static IWebHost BuildWebHost(string[] args) =>
              WebHost.CreateDefaultBuilder(args)
                  .ConfigureAppConfiguration((hostingContext, config) =>
                  {
                      config.SetBasePath(Directory.GetCurrentDirectory());
                      config.AddJsonFile("appsettings.json", optional: true, reloadOnChange: true)
                            .AddJsonFile($"appsettings.{hostingContext.HostingEnvironment.EnvironmentName}.json", optional: true, reloadOnChange: true);
                      config.AddEnvironmentVariables();
                      config.AddCommandLine(args);
                  })
                  .UseStartup<Startup>()
                  .Build();
      }
      

      我删除了其他部分只是为了使配置解释更容易。

      注意配置生成器中的.AddCommandLine(args) 行。

      与@BanksySan 的回答不同,您不需要创建静态属性,而是让 DI 将 IConfiguration 注入到启动类中。

      public class Startup
      {
          public Startup(IConfiguration configuration)
          {
              Configuration = configuration;
          }
      
          private IConfiguration Configuration { get; }
      

      您现在可以使用来自任何配置提供程序、文件、环境变量和命令行的配置条目。

      例子:

      dotnet 运行 --seed true

          public void Configure(IApplicationBuilder app)
          {
              app.UseExceptionHandler("/Home/Error");
      
              var seed = Configuration.GetValue<bool>("seed");
              if (seed)
                  SeedData.Initialize(app);
      
              app.UseStaticFiles();
              app.UseMvcWithDefaultRoute();
          }
      

      希望这可以进一步帮助某人。

      【讨论】:

      • 当在 Windows 服务中托管 ASP.NET Core 时,我也能够在我的 Worker.cs 类上做同样的事情 - 添加一个接受 IConfiguration 对象的构造函数也在那里工作。跨度>
      【解决方案4】:

      DavidG's answer 是正确的,但我仍然缺少一些拼图。

      您需要两个 Nuget 包:

      1. Microsoft.Extensions.Configuration.Binder
      2. Microsoft.Extensions.Configuration.CommandLine

      因为我们需要命令行参数,所以我们需要在Main(string[])中创建配置。

      using Microsoft.Extensions.Configuration;
      
      class Program
      {
          private static int Main(string[] args)
          {
              const string PORT = "12345";
      
              var listeningUrl = $"http://localhost:{PORT}";
              var configuration = new ConfigurationBuilder()
                                  .AddCommandLine(args)
                                  .Build();
              // Set the `static` `Configuration` property on the `Startup` class.
              Startup.Configuration = configuration;
      
              var builder = new WebHostBuilder()
                  .UseStartup<Startup>()
                  .UseKestrel()
                  .UseSetting("Message", "Hello World")
                  .UseUrls(listeningUrl);
      
              var host = builder.Build();
              WriteLine($"Running on {listeningUrl}");
              host.Run();
      
              return SUCCESS_EXIT_CODE;
          }
      }
      

      Startup 类是:

      using Microsoft.Extensions.Configuration;
      
      public class Startup
      {
          public static IConfiguration Configuration { get; set; }
      
      
          public void Configure(IApplicationBuilder app)
          {
              foreach (var c in Configuration.AsEnumerable())
                  Console.WriteLine($"{c.Key,-15}:{c.Value}");
          }
      }
      

      如果命令参数是--port 6000 outputDirectory C:\Temp 那么这将输出:

      port            :6000
      outputDirectory :C:\Temp
      

      【讨论】:

      【解决方案5】:

      如果您只需要将原始命令行参数传递给进程,或者您不想将它们添加到配置中,您仍然可以使用以下内容:

      Environment.GetCommandLineArgs();
      

      【讨论】:

        猜你喜欢
        • 2020-03-18
        • 2015-06-09
        • 2017-10-22
        • 2019-10-12
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多