简体   繁体   中英

Register an IConsumer<T> with dependency in Masstransit using Autofac

I have 2 systems, one for publish messages and other for consume them. Both are using Masstransit (with RabbitMQ) and are implemented using ASP.Net web api 2 and OWIN (and Autofac as IoC container). Everything works fine if my consumer has no dependencies, but when I inject a dependenciy into my consumer, the Consume method is never executed (no error is throwing during initialization).

This is the relevant Publisher code:

//Startup.cs
public class Startup
{
    public void Configuration(IAppBuilder app)
    {
        HttpConfiguration config = new HttpConfiguration();

        IContainer container = null;
        var builder = new ContainerBuilder();

        builder.Register(context =>
        {
            var busControl = Bus.Factory.CreateUsingRabbitMq(cfg =>
            {
                IRabbitMqHost rabbitMqHost = cfg.Host(new Uri(ConfigurationManager.AppSettings["RabbitMQHost"]), settings =>
                {
                    settings.Username(ConfigurationManager.AppSettings["RabbitMQUser"]);
                    settings.Password(ConfigurationManager.AppSettings["RabbitMQPassword"]);
                });
            });

            return busControl;
        })
        .As<IBusControl>()
        .As<IBus>()
        .SingleInstance();

        // Register Web API controllers
        builder.RegisterApiControllers(Assembly.GetExecutingAssembly());

        // Resolve dependencies
        container = builder.Build();
        config.DependencyResolver = AutofacWebApiDependencyResolver(container);

        WebApiConfig.Register(config);
        SwaggerConfig.Register(config);
        app.UseCors(CorsOptions.AllowAll);

        // Register the Autofac middleware FIRST.
        app.UseAutofacMiddleware(container);
        app.UseWebApi(config);

        // Starts MassTransit Service bus, and registers stopping of bus on app dispose
        var bus = container.Resolve<IBusControl>();
        var busHandle = bus.StartAsync();
        var properties = new AppProperties(app.Properties);
        if (properties.OnAppDisposing != CancellationToken.None)
        {
            properties.OnAppDisposing.Register(() => busHandle.Result.StopAsync(TimeSpan.FromSeconds(30)));
        }
    }
}

// Controller
public IHttpActionResult Post()
{
    _bus.Publish<IFooMessage>(new
    {
        Foo = "Foo"
    });

    return Ok();
}

And this is the relevant Consumer code:

// Startup.cs
public class Startup
{
    public void Configuration(IAppBuilder app)
    {
        HttpConfiguration config = new HttpConfiguration();

        IContainer container = null;
        var builder = new ContainerBuilder();

        builder.RegisterType<FooService>().As<IFooService>().InstancePerRequest();
        builder.RegisterModule<BusModule>();
        builder.RegisterModule<ConsumersModule>();

        // Register Web API controllers
        builder.RegisterApiControllers(Assembly.GetExecutingAssembly());

        // Resolve dependencies
        container = builder.Build();
        config.DependencyResolver = new AutofacWebApiDependencyResolver(container);

        WebApiConfig.Register(config);
        SwaggerConfig.Register(config);
        app.UseCors(CorsOptions.AllowAll);

        // Register the Autofac middleware FIRST.
        app.UseAutofacMiddleware(container);
        app.UseWebApi(config);

        // Starts MassTransit Service bus, and registers stopping of bus on app dispose
        var bus = container.Resolve<IBusControl>();
        var busHandle = bus.StartAsync();
        var properties = new AppProperties(app.Properties);
        if (properties.OnAppDisposing != CancellationToken.None)
        {
            properties.OnAppDisposing.Register(() => busHandle.Result.StopAsync(TimeSpan.FromSeconds(30)));
        }
    }
}

// BusModule.cs
public class BusModule : Module
{
    protected override void Load(ContainerBuilder builder)
    {
        builder.Register(context =>
        {
            var busControl = Bus.Factory.CreateUsingRabbitMq(cfg =>
            {
                IRabbitMqHost rabbitMqHost = cfg.Host(new Uri(ConfigurationManager.AppSettings["RabbitMQHost"]), settings =>
                {
                    settings.Username(ConfigurationManager.AppSettings["RabbitMQUser"]);
                    settings.Password(ConfigurationManager.AppSettings["RabbitMQPassword"]);
                });
                cfg.ReceiveEndpoint(rabbitMqHost, "IP.AgilePoint.queue", ec =>
                {
                    ec.LoadFrom(context);
                });
            });

            return busControl;
        })
        .SingleInstance()
        .As<IBusControl>()
        .As<IBus>();
    }
}

// ConsumerModule.cs
public class ConsumersModule : Module
{
    protected override void Load(ContainerBuilder builder)
    {
        builder.RegisterType<FooConsumer>();
    }
}

// FooConsumer.cs
public class FooConsumer : IConsumer<IFooMessage>
{
    private IFooService _service;

    public FooConsumer(IFooService service)
    {
        _service = service;
    }

    public Task Consume(ConsumeContext<IFooMessage> context)
    {
        IFooMessage @event = context.Message;

        _service.DoStuff(@event.Foo);

        return Task.FromResult(context.Message);
    }
}

Note my FooConsumer has a dependency (constructor) on IFooService. I've followed Masstransit documentation but I can't get this to work. What am I doing wrong?

Framework versions:

  • .Net Framework 4.6.1
  • Autofac: 3.5.2
  • Masstransit: 3.5.7

Updated:

Code can be found in this Github repository

I'd suggest looking at the documentation specific to Autofac, it's a fully supported container via the extension library.

http://masstransit-project.com/MassTransit/usage/containers/autofac.html

The package: https://www.nuget.org/packages/masstransit.autofac

Finally I found what I was doing wrong. For some reason I couldn't see my queues in RabbitMQ Management. When I have been able to see the error queue, I noticed de following error:

RabbitMQ错误

I was registering my IFooService in this way:

builder.RegisterType<FooService>().As<IFooService>().InstancePerRequest();

The InstancePerRequest() was causing the error. If I register the service with builder.RegisterType<FooService>().As<IFooService>() everything works fine. I Think this is because my bus instance is working as singleton (registered as SingleIsntace() ). The fact of using a web api project to host my bus/consumers caused me confusion.

Anyway, thanks to @Chris Patterson and @Alexey Zimarev for pointint me in the right direction of implementation (using MT extension to register consumers).

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM