es.davy.ai

Preguntas y respuestas de programación confiables

¿Tienes una pregunta?

Si tienes alguna pregunta, puedes hacerla a continuación o ingresar lo que estás buscando.

Fallo al inyectar un servicio al Consumidor en una aplicación de servicio de Windows (.Net Core 3.1) utilizando MassTransit.

Intento inyectar un ITest al constructor de Consumer en una aplicación de servicio de Windows utilizando MassTransit, pero falla.

Esto es lo que he intentado:

Program.cs

public class Program
{
    static void Main(string[] args)
    {
        CreateHostBuilder(args).Build().Run();
    }

    public static IHostBuilder CreateHostBuilder(string[] args) =>
        Host.CreateDefaultBuilder(args)
            .ConfigureServices((hostContext, services) =>
            {
                ConfigureServices(services);
            }).UseWindowsService();

    private static void ConfigureServices(IServiceCollection services)
    {
        services.AddHostedService<testservice>();

        var configuration = new ConfigurationBuilder()
            .SetBasePath(Directory.GetCurrentDirectory())
            .AddJsonFile("appsettings.json")
            .Build();
        services.AddTransient<itest, test="">();
    }
}

TestService.cs

public class TestService : BackgroundService
{
    private IBusControl _bus;

    public TestService()
    {
    }

    protected async override Task ExecuteAsync(CancellationToken stoppingToken)
    {
        _bus = Bus.Factory.CreateUsingAzureServiceBus(cfg =>
        {
            cfg.Host("myconnection");
            cfg.ReceiveEndpoint("myqueue", endpoint =>
            {
                endpoint.Consumer<testconsumer>(); //error when build the project
            });
        });

        await _bus.StartAsync();
    }
}

TestConsumer.cs

public class TestConsumer : IConsumer<mytestobject>
{
    private ITest _test;

    public TestConsumer(ITest test)
    {
        _test = test;
    }

    public async Task Consume(ConsumeContext<mytestobject> context)
    {            
    }
}

Cuando compilo todo el proyecto, obtengo un error CS0310:

El tipo … debe ser un tipo no abstracto con un constructor público sin parámetros para poder utilizarlo como parámetro …

He buscado y han utilizado services.AddMassTransit en la función ConfigureServices. Pero en mi aplicación utilizo un servicio de Windows, no una aplicación de consola.

Entonces, ¿cómo puedo inyectar mi ITest en el constructor de TestService?</itest,>

Tags:  , , , ,

Answer

  1. Avatar for davy.ai

    Para inyectar ITest en TestConsumer usando MassTransit en una aplicación de servicio de Windows, es necesario configurar MassTransit con las interfaces IServiceCollection e IBusRegistrationContext. Aquí te mostramos cómo puedes modificar tu código para lograrlo:

    Program.cs

    public class Program
    {
        static void Main(string[] args)
        {
            CreateHostBuilder(args).Build().Run();
        }
    
        public static IHostBuilder CreateHostBuilder(string[] args) =>
            Host.CreateDefaultBuilder(args)
                .ConfigureServices((hostContext, services) =>
                {
                    ConfigureServices(services, hostContext.Configuration);
                }).UseWindowsService();
    
        private static void ConfigureServices(IServiceCollection services, IConfiguration configuration)
        {
            services.AddHostedService<testservice>();
    
            services.AddScoped<itest, test="">();
    
            services.AddMassTransit(x =>
            {
                x.AddConsumer<testconsumer>();
                x.AddBus(provider => Bus.Factory.CreateUsingAzureServiceBus(cfg =>
                {
                    cfg.Host(configuration["AzureServiceBus:ConnectionString"]);
                    cfg.ReceiveEndpoint("myqueue", ep =>
                    {
                        ep.ConfigureConsumer<testconsumer>(provider);
                    });
                }));
            });
    
            services.AddMassTransitHostedService();
        }
    }
    

    En ConfigureServices(), hemos agregado las siguientes líneas de código:

    services.AddScoped<itest, test="">();
    
    services.AddMassTransit(x =>
    {
        x.AddConsumer<testconsumer>();
        x.AddBus(provider => Bus.Factory.CreateUsingAzureServiceBus(cfg =>
        {
            cfg.Host(configuration["AzureServiceBus:ConnectionString"]);
            cfg.ReceiveEndpoint("myqueue", ep =>
            {
                ep.ConfigureConsumer<testconsumer>(provider);
            });
        }));
    });
    
    services.AddMassTransitHostedService();
    

    Aquí hemos registrado ITest como un servicio con ámbito en IServiceCollection. También hemos agregado los servicios de MassTransit y la instancia del bus utilizando IServiceCollection.

    En AddMassTransit(), especificamos que queremos agregar TestConsumer al registro de consumidores. También creamos la instancia del bus utilizando Bus.Factory.CreateUsingAzureServiceBus() y lo configuramos para escuchar en el punto final myqueue.

    En AddBus(), inyectamos IServiceProvider para que MassTransit pueda resolver la instancia de TestConsumer e inyectar ITest.

    En AddMassTransitHostedService(), registramos los servicios alojados de MassTransit en IServiceCollection. Esto iniciará y detendrá el bus como un servicio en segundo plano cuando el servicio de Windows se inicie y se detenga.

    TestConsumer.cs se mantiene igual:

    public class TestConsumer : IConsumer<mytestobject>
    {
        private ITest _test;
    
        public TestConsumer(ITest test)
        {
            _test = test;
        }
    
        public async Task Consume(ConsumeContext<mytestobject> context)
        {            
        }
    }
    

    Con estas modificaciones, ahora deberías poder inyectar ITest en TestConsumer exitosamente.</itest,></itest,>

Comments are closed.