Как в консольном asp.net core 6 приложении получить из DI нужную зависимость и выполнить с ней код?
Есть внешняя шина (RabbitMQ) в которую некий внешний сервис паблишит команды. У меня есть консольное asp.net core 6 приложение (в дальнейшем будет завернуто в докер), в котором через внедрение зависимостей средствами easynetq подключаюсь к шине, а дальше мне необходимо подписаться на очередь, чтобы иметь возможность обрабатывать команды от внешнего сервиса. Проблема в том, что я недостаточно хорошо знаю asp.net core, поэтому не могу правильно зарегистрировать слушателя (consumer), чтобы этот код выполнился после запуска приложения.
Предустановки:
- ASP.NET Core 6 консольное приложение.
- Для взаимодействия с RabbitMQ используется библиотека EasyNetQ.
- Подключение к шине осуществляется через 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 - новая для меня технология.