如何访问托管服务中的作用域服务,使用 SimpleInjector 执行依赖项注入

问题描述 投票:0回答:1

我有一个使用简单注入器的旧 .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”。)

我将不胜感激任何帮助或建议,由于数据问题,一些类名称已更改。

rabbitmq simple-injector asp.net-core-hosted-services ihostedservice
1个回答
0
投票

我认为呼叫是在以下行中:

services.AddHostedService<UpdateApntService>();

UpdateApntService
似乎依赖于可能在简单注入器中注册的服务。然而,上面的注册并没有将托管服务添加到 Simple Injector,而是添加到内置配置系统。

因此,解决方案是删除该行代码并将其替换为文档中建议的代码,即:

services.AddSimpleInjector(container, options =>
{
    options.AddHostedService<UpdateApntService>();
});
© www.soinside.com 2019 - 2024. All rights reserved.