Настройка в WorkerService

#c# #.net-core #dependency-injection

#c# #.net-ядро #внедрение зависимостей

Вопрос:

В обычной службе .net core шаблон создал бы для меня такую функцию :

 public void Configure(IApplicationBuilder app)
{
    ...
}
 

Здесь я могу внедрить свои сервисы и использовать их при запуске, например, сценарий предварительного развертывания базы данных.

В шаблоне рабочей службы эта функция не создается для меня, только функция CreateHostbuilder .

Как мне создать функцию Configure() или запустить / сконструировать класс при запуске в рабочей службе?

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

1. Вы имеете в виду, что хотите использовать внедрение зависимостей из консольного процесса? docs.microsoft.com/en-us/dotnet/core/extensions/generic-host

2. Подсказка, .ConfigureServices(...) не обязательно должно быть лямбда. Вы можете определить статический метод.

3. В workerService шаблоне нет метода Configure, я не знаю, зачем вам нужно его создавать?

4. @osmanRahimi, потому что я хочу создать класс один раз при обновлении состояния службы.

5. таким образом, вы можете зарегистрировать свои интерфейсы / класс, как и раньше, используя сервисы в ConfigureServices

Ответ №1:

Итак, вы хотите настроить службы, а затем использовать их из консольного приложения.

Из вашего вопроса и комментариев кажется, что вы понимаете, как настраивать службы;

 public static IHostBuilder CreateHostBuilder(string[] args) =>
        Host.CreateDefaultBuilder(args)
                ...
                .ConfigureServices(ConfigureServices);
public static void ConfigureServices(HostBuilderContext context, IServiceCollection serviceCollection) {
    ...
}
 

Теперь у вас есть несколько способов использовать эти службы. Вы можете запустить хост, затем получить сервисы и использовать их в своем основном методе. Выход, когда ваша работа выполнена и все службы удалены.

 public static async Task<int> Main(string[] args)
{
    using (var host = CreateHostBuilder(args).Build())
    {
        await host.StartAsync();
        var lifetime = host.Services.GetRequiredService<IHostApplicationLifetime>();
        var logger = host.Services.GetRequiredService<ILogger<Program>>();
        ...
        lifetime.StopApplication();
        await host.WaitForShutdownAsync();
    }
    return 0;
}
 

Или вы могли бы выполнять текущие задачи, реализуя IHostedService / BackgroundService . При IHost запуске все зарегистрированные IHostedService будут запущены в том порядке, в котором они были зарегистрированы, а затем остановлены / отменены при завершении работы хоста.

 public static async Task<int> Main(string[] args)
{
    using (var host = CreateHostBuilder(args).Build())
    {
        await host.RunAsync();
    }
    return 0;
}

public static void ConfigureServices(HostBuilderContext context, IServiceCollection serviceCollection) {
    serviceCollection.AddHostedService<Service>();
}

public class Service : BackgroundService {
    public Service (...) {...}
    protected override async Task ExecuteAsync(CancellationToken stoppingToken)
    {
        await Task.Yield();
        while (!stoppingToken.IsCancellationRequested)
        {
            ...
        }
    }
}
 

Или некоторая комбинация из вышеперечисленных.

Обратите внимание, что когда вы используете веб-хост, это IHostedService функция ( GenericWebHostedService ), которая фактически запускает веб-сервер. Вызов всех зарегистрированных IStartupFilters , включая тот, который вызывает ваш Startup.Configure метод, для компиляции конвейера запросов.

Ответ №2:

Если вы хотите зарегистрировать интерфейс или службу, чтобы внедрить их в другие службы, вы все равно можете зарегистрировать свои службы ConfigureServices .

в следующем примере есть две службы, которые регистрируются как Singleton и Transient .

 public static IHostBuilder CreateHostBuilder(string[] args) =>
        Host.CreateDefaultBuilder(args)
            .ConfigureServices((hostContext, services) =>
            {
                services.AddHostedService<Worker>();
                services.AddSingleton<IEmployeeService, EmployeeService>();
                services.AddTransient<UserService>();
            });