Как в консольном asp.net core 6 приложении получить из DI нужную зависимость и выполнить с ней код?

Есть внешняя шина (RabbitMQ) в которую некий внешний сервис паблишит команды. У меня есть консольное asp.net core 6 приложение (в дальнейшем будет завернуто в докер), в котором через внедрение зависимостей средствами easynetq подключаюсь к шине, а дальше мне необходимо подписаться на очередь, чтобы иметь возможность обрабатывать команды от внешнего сервиса. Проблема в том, что я недостаточно хорошо знаю asp.net core, поэтому не могу правильно зарегистрировать слушателя (consumer), чтобы этот код выполнился после запуска приложения.

Предустановки:

  1. ASP.NET Core 6 консольное приложение.
  2. Для взаимодействия с RabbitMQ используется библиотека EasyNetQ.
  3. Подключение к шине осуществляется через DI, предоставляемый библиотекой EasyNetQ.DI.Microsoft (классический вариант использования EasyNetQ не поддерживает DI).
// Program.cs
var builder = WebApplication.CreateBuilder(args);

builder.Services.CustomRegisterEasyNetQ();
builder.Services.AddControllers();
builder.Services.AddEndpointsApiExplorer();
builder.Services.AddConfigOptions(builder.Configuration);

var app = builder.Build();

app.UseHttpsRedirection();
app.UseAuthorization();
app.MapControllers();

app.Run();

Где builder.Services.CustomRegisterEasyNetQ(); - это extension-класс, чтобы вынести подключение к шине за пределы Program.cs.

public static class EasyNetQExtension
{
    public static IServiceCollection CustomRegisterEasyNetQ(this IServiceCollection services)
    {
        services.RegisterEasyNetQ(resolver =>
        {
            var busOptions = resolver.Resolve<IOptions<BusOptions>>();
            if (busOptions == null)
                throw new NullReferenceException(nameof(busOptions));

            var conStrParser = resolver.Resolve<IConnectionStringParser>();
            if (conStrParser == null)
                throw new NullReferenceException(nameof(conStrParser));

            return conStrParser.Parse(busOptions.Value.ConnectionString);
        }, register =>
        {
            register.EnableNewtonsoftJson();
            register.EnableConsoleLogger();
        });

        return services;
    }
}

После внедрения зависимости builder.Services.CustomRegisterEasyNetQ(); становится доступным интерфейс взаимодействия с шиной IBus. Для регистрации слушателя на шине нужно выполнить примерно следующий код:

bus.PubSub.Subscribe<ServiceCommand>("QueueName", ServiceCommandHandler.Handle);

Собственно куда добавить добавить эту строчку я и не понимаю. Необходимо, чтобы был доступен и уже проинициализирован IBus, а строчка запускалась один раз за все время, пока работает консольное приложение. Не удалось нагуглить ничего лучше, чем добавить в Program.cs перед app.Run(); примерно такой код:

app.Lifetime.ApplicationStarted.Register(() =>
{
    var bus = app.Services.GetService<IBus>();
    if (bus == null)
        return;

    bus.PubSub.Subscribe<ServiceCommand>("QueueName", ServiceCommandHandler.Handle);
});

Есть ли более правильное решение моей проблемы, чтобы этот код выполнялся 1 раз после запуска приложения, был вынесен за пределы Program.cs и можно было получить IBus?

Прошу прощения, если кому-то вопрос покажется глупым, ASP.NET Core - новая для меня технология.


Ответы (0 шт):