Как я могу получить доступ к аргументам командной строки в консольном приложении с помощью IHostedService?

#.net #.net-core #console-application #ihostedservice

#.net #.net-ядро #консольное приложение #ихостедсервис

Вопрос:

Я не могу понять, как получить доступ к аргументам командной строки в моем ConsoleHostedService классе реализации. Я вижу, что в источниках CreateDefaultBuilder(args) каким-то образом добавляется это в конфигурацию … с именем Args

Наличие основной программы:

 internal sealed class Program
{
    private static async Task Main(string[] args)
    {
        await Host.CreateDefaultBuilder(args)
            .UseContentRoot(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location))
            .ConfigureServices((context, services) =>
            {
                services.AddHostedService<ConsoleHostedService>();
            })
            .RunConsoleAsync();
    }
}
 

и размещенный сервис:

 internal sealed class ConsoleHostedService : IHostedService
{
    public ConsoleHostedService(
        IHostApplicationLifetime appLifetime,
        IServiceProvider serviceProvider)
    {
        //...
    }
}
 

Комментарии:

1. System.Environment.GetCommandLineArguments() ?

2. Это зависит от того, что вы на самом деле пытаетесь извлечь из командной строки. Приведите пример варианта использования

3. @Nkosi: У меня такое чувство, что этого определенно не должно быть. Я хотел бы получить доступ к массиву args таким, какой он есть

4. @Dai Спасибо, это будет запасной план, хотя, вероятно, это не тот. ЧИСТЫЙ предполагаемый способ, если только не было бы CreateDefaultBuilder(args) вызвано точно main ‘s args . Кроме того Environment.CommandLine , это монолитная строка, конечно, я могу разделить ее на пробел, но она была бы менее подвержена ошибкам и более совместима, если бы я получил исходный массив OS

5. Тот, который передается в configuration, предназначен для обеспечения привязки конфигурации к строгим типам через CommandLineConfigurationProvider docs.microsoft.com/en-us/aspnet/core/fundamentals/configuration /…

Ответ №1:

Я не верю, что существует встроенный метод DI для получения аргументов командной строки, но, вероятно, причина в том, что обработка аргументов командной строки является обязанностью вашего хост-приложения, и это должно передавать информацию о хосте / среде через IConfiguration и т.д. IOptions

В любом случае, просто определите свои собственные вводимые:

 public interface IEntrypointInfo
{
    String CommandLine { get; }

    IReadOnlyList<String> CommandLineArgs { get; }

    // Default interface implementation, requires C# 8.0 or later:
    Boolean HasFlag( String flagName )
    {
        return this.CommandLineArgs.Any( a => ( "-"   a ) == flagName || ( "/"   a ) == flagName );
    }
}

/// <summary>Implements <see cref="IEntrypointInfo"/> by exposing data provided by <see cref="System.Environment"/>.</summary>
public class SystemEnvironmentEntrypointInfo : IEntrypointInfo
{
    public String CommandLine => System.Environment.CommandLine;

    public IReadOnlyList<String> CommandLineArgs => System.Environment.GetCommandLineArgs();
}

/// <summary>Implements <see cref="IEntrypointInfo"/> by exposing provided data.</summary>
public class SimpleEntrypointInfo : IEntrypointInfo
{
    public SimpleEntrypointInfo( String commandLine, String[] commandLineArgs )
    {
        this.CommandLine = commandLine ?? throw new ArgumentNullException(nameof(commandLine));
        this.CommandLineArgs = commandLineArgs ?? throw new ArgumentNullException(nameof(commandLineArgs));
    }

    public String CommandLine { get; }

    public IReadOnlyList<String> CommandLineArgs { get; }
}

//

public static class Program
{
    public static async Task Main( String[] args )
    {
        await Host.CreateDefaultBuilder( args )
            .UseContentRoot(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location))
            .ConfigureServices((context, services) =>
            {
                services.AddHostedService<ConsoleHostedService>();
                services.AddSingleton<IEntrypointInfo,SystemEnvironmentEntrypointInfo>()
            })
            .RunConsoleAsync();
    }
 

Для автоматизированных модульных и интеграционных тестов используйте SimpleEntrypointInfo .