我有一个使用简单注入器的旧 .NET 应用程序,其中服务被注册为作用域。不过,我添加了一个
HostedService
服务来使用 RabbitMQ 队列。在此服务中,我需要访问已注册的服务,例如配置服务。
我已经尝试使用here所示的替代方案,但使用简单注射器不起作用。
Startup.class
public class Startup
{
private readonly Container _container = InjectorUtil.CreateContainer();
private ISettings AppSettings { get; }
public Startup(IConfiguration configuration, IWebHostEnvironment env)
{
// Set to false. This will be the default in v5.x and going forward.
_container.Options.ResolveUnregisteredConcreteTypes = false;
AppSettings = configuration.Get<ISettings>();
}
public void ConfigureServices(IServiceCollection services)
{
***
InitializeContainer();
***
//RabbitMQ
InitializeRabbitMQ(services);
}
private void InitializeContainer()
{
new MapperProvider(_container).Load();
new EntityFrameworkCoreSimpleInjector(_container, AppSettings).Load();
new DominioServicosSimpleInjector(_container, AppSettings).Load();
}
private void InitializeRabbitMQ(IServiceCollection services)
{
services.AddSingleton(GetConnectionFactory(AppSettings));
services.AddSingleton(GetQueueApontamentoConfig(AppSettings));
services.AddSingleton<RabbitProducerService>();
services.AddSingleton<RabbitConsumerService>();
services.AddHostedService<UpdateApntService>();
}
private ConnectionFactory GetConnectionFactory(IRabbitMQSettings rabbitMQSettings)
{
return new ConnectionFactory
{
UserName = rabbitMQSettings.RABBIT_MQ_USER_NAME,
Password = rabbitMQSettings.RABBIT_MQ_PASSWORD,
VirtualHost = rabbitMQSettings.RABBIT_MQ_VIRTUAL_HOST,
HostName = rabbitMQSettings.RABBIT_MQ_HOST
};
}
private ApontamentoQueueConfig GetQueueApontamentoConfig(IRabbitMQSettings rabbitMQSettings)
{
return new ApnQueueConfig
{
Exchange = rabbitMQSettings.RABBIT_MQ_APONT_EXCHANGE,
Queue = rabbitMQSettings.RABBIT_MQ_APONT_QUEUE,
Rounting = rabbitMQSettings.RABBIT_MQ_APONT_ROUTING_KEY
};
}
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
app.UsePathBase("/api");
app.UseSwagger();
app.UseSwaggerUI(c =>
{
c.SwaggerEndpoint("./api/swagger.json", "PRONT");
});
app.UseSimpleInjector(_container);
if (AppSettings.APP_USE_HSTS) app.UseHsts();
app.UseErrorLogging();
app.UseRouting();
app.UseCors(builder =>
{
builder
.AllowAnyOrigin()
.AllowAnyMethod()
.AllowAnyHeader();
});
***
app.UseDefaultFiles();
app.UseStaticFiles(new StaticFileOptions
{
FileProvider = new PhysicalFileProvider(
Path.Combine(env.WebRootPath, "ajuda")),
RequestPath = "/ajuda"
});
app.UseStaticFiles(new StaticFileOptions
{
FileProvider = new PhysicalFileProvider(
Path.Combine(env.WebRootPath, "manutencao")),
RequestPath = "/manutencao"
});
app.UseAuthentication();
app.UseAuthorization();
app.UseProntAuthentication();
app.UseEndpoints(endpoints =>
{
endpoints.MapControllerRoute(
name: "default",
pattern: "{controller}/{action=Index}/{id?}");
});
_container.Verify();
}
}
更新ApntService.class
public class UpdateApntService : BackgroundService
{
readonly RabbitConsumerService _consumerService;
readonly ApntQueueConfig _apntQueueConfig;
readonly IConfigurationService _configurationService;
public UpdateApntService(
RabbitConsumerService consumerService,
ApntQueueConfig apntQueueConfig,
IConfigurationService configurationService)
{
_consumerService = consumerService;
_apntQueueConfig = apntQueueConfig;
_configurationService = configurationService;
}
protected override Task ExecuteAsync(CancellationToken stoppingToken)
{
var config = _configurationService.GetCurrent();
_consumerService.AddListener(_apntQueueConfig.Queue, (_, args) =>
{
var body = args.Body.ToArray();
var message = Encoding.UTF8.GetString(body);
var apontamento = JsonSerializer.Deserialize<apntDTO>(message)!;
// execute updateApnt
});
return Task.CompletedTask;
}
}
异常
某些服务无法构建(验证服务描述符“ServiceType:Microsoft.Extensions.Hosting.IHostedService Lifetime:Singleton ImplementType:Pront.Dominio.Servico.Services.RabbitMQ.UpdateApntService”时出错:无法解析类型的服务)尝试激活“xxxx.RabbitMQ.UpdateApntService”时出现“xxxxx.ConfiguracoesService”。)
我将不胜感激任何帮助或建议,由于数据问题,一些类名称已更改。
我认为呼叫是在以下行中:
services.AddHostedService<UpdateApntService>();
UpdateApntService
似乎依赖于可能在简单注入器中注册的服务。然而,上面的注册并没有将托管服务添加到 Simple Injector,而是添加到内置配置系统。
因此,解决方案是删除该行代码并将其替换为文档中建议的代码,即:
services.AddSimpleInjector(container, options =>
{
options.AddHostedService<UpdateApntService>();
});