'Fail to inject a service to Consumer in a Windows service application (.Net Core 3.1) using MassTransit

I try to inject an ITest to Consumer constructor in a Windows service application using MassTransit but it fails.

This is what I've tried:

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)
    {            
    }
}

When I build the whole project I got an error CS0310

The type ... must be a non-abstract type with a public parameterless constructor in order to use it as parameter ...

I searched and they use services.AddMassTransit in the ConfigureServices function. But in my application I use as a Windows service, not a console application.

So how can I inject my ITest to the constructor of TestService?



Solution 1:[1]

You instantiate the bus inside the background service. There's no connection between the DI container and the bus instance. How do you expect anything to be injected into the consumer in this case?

All you need to do is to follow the documentation, and it will work.

Configure MassTransit for ASP.NET Core using the example provided, move the bus instantiation to the ConfigureServices function, remove your background service and use the provided MassTransitHostedService as described in the docs.

    public void ConfigureServices(IServiceCollection services)
    {
        services.AddMassTransit(x =>
        {
            x.AddConsumer<EventConsumer>();

            x.UsingRabbitMq((context, cfg) =>
            {
                cfg.ReceiveEndpoint("event-listener", e =>
                {
                    e.ConfigureConsumer<EventConsumer>(context);
                });
            });
        });

        services.AddMassTransitHostedService();
    }

It doesn't matter if you are in Windows service, Docker container, or whatever.

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 Alexey Zimarev