使用CreateApplicationBuilder时,如何传递命令行参数数组给ClientHostedService?
解决.NET HostedService获取原始string[]命令行参数的问题
方法一:直接通过依赖注入传递原始args
这是最直接可靠的方案,在Main方法中将原始string[] args注册为单例服务,然后在ClientHostedService的构造函数中直接接收使用。
public static async Task<int> Main(string[] args) { var builder = Host.CreateApplicationBuilder(args); // 将原始命令行参数注册为单例 builder.Services.AddSingleton(args); builder.Services.AddHostedService<ClientHostedService>(); IHost host = builder.Build(); await host.StartAsync(); await host.StopAsync(); return 0; } // ClientHostedService实现 public class ClientHostedService : IHostedService { private readonly string[] _commandLineArgs; // 构造函数注入原始参数 public ClientHostedService(string[] args) { _commandLineArgs = args; } public Task StartAsync(CancellationToken cancellationToken) { // 直接将参数传给CommandLineParser var parser = new CommandLineParser(); var parseResult = parser.ParseArguments<YourCommandOptions>(_commandLineArgs); // 后续业务逻辑处理 return Task.CompletedTask; } public Task StopAsync(CancellationToken cancellationToken) { return Task.CompletedTask; } }
方法二:通过自定义配置源存储原始参数
如果需要让原始参数在整个配置系统中可访问,可以自定义配置源来保存args,后续从配置提供者中提取:
// 自定义配置源 public class OriginalArgsConfigurationSource : IConfigurationSource { private readonly string[] _args; public OriginalArgsConfigurationSource(string[] args) => _args = args; public IConfigurationProvider Build(IConfigurationBuilder builder) { return new OriginalArgsConfigurationProvider(_args); } } // 自定义配置提供者 public class OriginalArgsConfigurationProvider : ConfigurationProvider { public string[] OriginalArgs { get; } public OriginalArgsConfigurationProvider(string[] args) { OriginalArgs = args; } } // Main方法中注册配置源 public static async Task<int> Main(string[] args) { var builder = Host.CreateApplicationBuilder(args); // 添加自定义配置源 builder.Configuration.Add(new OriginalArgsConfigurationSource(args)); builder.Services.AddHostedService<ClientHostedService>(); IHost host = builder.Build(); await host.StartAsync(); await host.StopAsync(); return 0; } // ClientHostedService中提取参数 public class ClientHostedService : IHostedService { private readonly string[] _commandLineArgs; public ClientHostedService(IConfiguration configuration) { // 找到自定义配置提供者 var argsProvider = configuration.GetProviders() .OfType<OriginalArgsConfigurationProvider>() .FirstOrDefault(); _commandLineArgs = argsProvider?.OriginalArgs ?? Array.Empty<string>(); } public Task StartAsync(CancellationToken cancellationToken) { var parser = new CommandLineParser(); var parseResult = parser.ParseArguments<YourCommandOptions>(_commandLineArgs); return Task.CompletedTask; } public Task StopAsync(CancellationToken cancellationToken) { return Task.CompletedTask; } }
不推荐的方法:反射访问CommandLineConfigurationProvider内部属性
虽然可以通过反射获取CommandLineConfigurationProvider中的原始参数,但该属性为内部成员,.NET版本更新可能导致失效,不建议生产环境使用:
public class ClientHostedService : IHostedService { private readonly string[] _commandLineArgs; public ClientHostedService(IConfiguration configuration) { var commandLineProvider = configuration.GetProviders() .OfType<CommandLineConfigurationProvider>() .FirstOrDefault(); if (commandLineProvider != null) { // 反射获取内部Args属性 var argsProp = typeof(CommandLineConfigurationProvider) .GetProperty("Args", System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.NonPublic); _commandLineArgs = argsProp?.GetValue(commandLineProvider) as string[] ?? Array.Empty<string>(); } else { _commandLineArgs = Array.Empty<string>(); } } // ... 其他方法 }
方案选择建议
优先使用方法一,实现简单、无版本依赖风险,完全满足CommandLineParser对string[]参数的需求。
内容的提问来源于stack exchange,提问作者Murat Erenturk
相关产品推荐
相关产品推荐

