.NET核心从Program.cs传递命令行Args到Startup.cs

时间:2016-12-22 19:40:39

标签: c# .net-core

我正在尝试配置kestrel,以便当它处于原始模式时,它会在特定端口上运行。但是为了这样做,似乎launchsettings.json需要通过命令行参数来执行此操作,因为没有直接选项,它总是在端口5000上运行,如果你有一个需要运行的api和一个网站,这显然会发生冲突

所以我将CommandLine包添加到我的站点,你确实可以在startup.cs文件中使用builder.AddCommandLine()。

问题是如何从program.cs到Startup.cs获取args或者查找静态变量以外的其他文件。

如果你无法获得args,那么扩展方法会变得毫无意义。

有更好的方法吗?

2 个答案:

答案 0 :(得分:6)

<强>更新

我实际上找到了更优雅的解决方案:

  1. 将命令行参数解析为Program中的IConfigurationRoot(使用CommandLineApplication,好文章&amp; examples here
  2. 只需通过DI容器将此IConfigurationRoot传递给Startup
  3. 像这样:

    public static IWebHost BuildWebHost(string[] args)
    {
        var configuration = LoadConfiguration(args);
    
        // Use Startup as always, register IConfigurationRoot to services
        return new WebHostBuilder()
            .UseKestrel()
            .UseConfiguration(configuration)
            .ConfigureServices(s => s.AddSingleton<IConfigurationRoot>(configuration))
            .UseStartup<Startup>()
            .Build();
    }
    
    public class Startup
    {
        public Startup(IConfigurationRoot configuration)
        {
            // You get configuration in Startup constructor or wherever you need
        }
    }
    

    LoadConfiguration的示例实现,它解析args和构建IConfigurationRoot(在此示例中,配置文件名可以在命令行参数中重写):

    private static IConfigurationRoot LoadConfiguration(string[] args)
    {
        var configurationFileName = "configuration.json";
    
        var cla = new CommandLineApplication(throwOnUnexpectedArg: true);
    
        var configFileOption = cla.Option("--config <configuration_filename>", "File name of configuration", CommandOptionType.SingleValue);
    
        cla.OnExecute(() =>
        {
            if (configFileOption.HasValue())
                configurationFileName = configFileOption.Value();
    
            return 0;
        });
    
        cla.Execute(args);
    
        return new ConfigurationBuilder()
            .SetBasePath(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location))
            .AddJsonFile(configurationFileName, optional: false, reloadOnChange: true)
            .AddCommandLine(args)
            .Build();
    }
    

    OLD ANSWER

    您可以自己实例化Startup类,并将其作为实例传递给WebHostBuilder。它有点不那么优雅,但可行。来自here.

    public static IWebHost BuildWebHost(string[] args)
    {
        // Load configuration and append command line args
        var config = new ConfigurationBuilder()
            .SetBasePath(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location))
            .AddJsonFile("configuration.json")
            .AddCommandLine(args)
            .Build();
    
        // pass config to Startup instance
        var startup = new Startup(config);
    
        // Instead of using UseStartup<Startup>()
        // Register startup to services
        return new WebHostBuilder()
            .UseKestrel()
            .UseSetting("applicationName", "Your.Assembly.Name")
            .UseConfiguration(config)
            .ConfigureServices(services => services.AddSingleton<IStartup>(startup))
            .Build();
    }
    

    一些警告是:

    • 通过这样做,Startup应该实现IStartup,其参数中的Configure方法仅限Configure(IApplicationBuilder app)而不是Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory, IApplicationLifetime lifetime)
    • 出于某种原因,您需要手动指定applicationName参数,如我的示例所示。我正在2.0.0-preview1-final
    • 上对此进行测试

答案 1 :(得分:5)

可以将Kestrel配置为以多种方式侦听不同的端口。这些方法都不需要在Startup类中进行,而是在Main类的Program方法中进行。使用AddCommandLine扩展方法就是其中之一。要使用它,请修改Program.cs文件的Main方法,如下所示:

public static void Main(string[] args)
{
    var config = new ConfigurationBuilder()
        .AddCommandLine(args)
        .Build();

    var host = new WebHostBuilder()
                .UseKestrel()
                .UseConfiguration(config)
                .UseStartup<Startup>()
                .Build();
    host.Run();
}

然后,使用dotnet run --server.urls http://*:<yourport>运行应用程序,将<yourport>替换为您希望它运行的实际端口号。 *使其侦听所有可用的IP地址,如果您想要侦听特定地址,则需要在那里指定,而不是*

更改端口的另一个选项是使用.UseUrls方法对端口和地址进行硬编码。例如:

public static void Main(string[] args)
{
    var host = new WebHostBuilder()
                .UseKestrel()
                .UseUrls("http://*:8080")
                .UseStartup<Startup>()
                .Build();
    host.Run();
}

此示例将使您的应用程序在所有可用IP地址上侦听端口8080