8

I'm trying to use DI with my consumer class without success.

My consumer class:

public class TakeMeasureConsumer : IConsumer<TakeMeasure>
{

    private IUnitOfWorkAsync _uow;
    private IInstrumentOutputDomainService _instrumentOutputDomainService;


    public TakeMeasureConsumer(IUnitOfWorkAsync uow,
        IInstrumentOutputDomainService instrumentOutputDomainService)
    {
        _uow = uow;
        _instrumentOutputDomainService = instrumentOutputDomainService;
    }


    public async Task Consume(ConsumeContext<TakeMeasure> context)
    {

        var instrumentOutput = Mapper.Map<InstrumentOutput>(context.Message);

        _instrumentOutputDomainService.Insert(instrumentOutput);
        await _uow.SaveChangesAsync();

    }
}

When I want to register the bus factory the consumer must have a parameterless constructor.

protected override void Load(ContainerBuilder builder)
{

    builder.Register(context =>
        Bus.Factory.CreateUsingRabbitMq(cfg =>
        {
            var host = cfg.Host(new Uri("rabbitmq://localhost/"), h =>
            {
                h.Username("guest");
                h.Password("guest");
            });

            cfg.ReceiveEndpoint(host, "intrument_take_measure", e =>
            {
                // Must be a non abastract type with a parameterless constructor....
                e.Consumer<TakeMeasureConsumer>();

            });  

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

Any help would be appreciated, I really don't know how to register my consumer...

Thanks

Guillaume Racicot
  • 39,621
  • 9
  • 77
  • 141
JoyC
  • 85
  • 1
  • 8

1 Answers1

12

Integrating with Autofac is easy, there are extension methods in the MassTransit.Autofac package that help out.

First, there is an AutofacConsumerFactory that will resolve your consumers from the container. You can add this to the container, or you can register it yourself using:

builder.RegisterGeneric(typeof(AutofacConsumerFactory<>))
    .WithParameter(new NamedParameter("name", "message"))
    .As(typeof(IConsumerFactory<>));

Then, in the builder statement for the bus and receive endpoint:

e.Consumer(() => context.Resolve<IConsumerFactory<TakeMeasureConsumer>());

This will then resolve your consumers from the container.

Update:

For newer versions of MassTransit add receive endpoints like this:

e.Consumer<TakeMeasureConsumer>(context);
Marius Stănescu
  • 3,603
  • 2
  • 35
  • 49
Chris Patterson
  • 28,659
  • 3
  • 47
  • 59
  • Hi Chris, this is now working for me. The masstransit.Autofac package makes it really easy and masstransit is awesome. Thanks! – JoyC Oct 08 '15 at 03:07
  • Chris Patterson, code in your answer seems is not working. context.Resolve - but you registered IConsumerFactory. When i changed that, i've got resolution issue: Autofac.Core.Activators.Reflection.DefaultConstructorFinder' on type 'MassTransit.AutofacIntegration.AutofacConsumerFactory`1 – flamedmg Oct 08 '15 at 11:13
  • Try like this: https://github.com/MassTransit/MassTransit/blob/develop/src/MassTransit.Host/ContainerBuilderExtensions.cs#L28 – Chris Patterson Oct 08 '15 at 18:48
  • Hi Chris, sorry to bother you again but I got this error now in the builder statement for the receive endpoint: The type 'AutofacConsumerFactory' cannot be used as type parameter 'TConsumer' in the generic type or method 'ConsumerExtensions.Consumer(IReceiveEndpointConfigurator, Func, Action>)'. There is no implicit reference conversion from 'MassTransit.AutofacIntegration.AutofacConsumerFactory' to 'MassTransit.IConsumer'. – JoyC Oct 14 '15 at 12:29
  • I edited the above to make sure it's right, that works and verified. – Chris Patterson Oct 14 '15 at 14:24
  • Thanks Chris, I was just missing to set up the lifetime scope for AutofacConsumerFactory, adding InstancePerLifetimeScope() has solved my issue, thanks again! – JoyC Oct 15 '15 at 23:46
  • Hi. I am using MassTransit 3.5.7 and I am trying to add multiple receive endpoints. Does it work with e.LoadFrom(context);? Or should I specify the consumer for each receive endpoint? I am trying to specify the consumers as you suggested, using IConsumerFactory, but I get the an error (posted in the following comment). Could you point me in the right direction, please? – Marius Stănescu Jul 21 '17 at 11:31
  • The type 'MassTransit.IConsumerFactory' cannot be used as type parameter 'TConsumer' in the generic type or method 'ConsumerExtensions.Consumer(IReceiveEndpointConfigurator, Func, Action>)'. There is no implicit reference conversion from 'MassTransit.IConsumerFactory' to 'MassTransit.IConsumer'. – Marius Stănescu Jul 21 '17 at 11:31
  • I succeded like this: e.Consumer(context); Can I update your answer with this line? – Marius Stănescu Jul 21 '17 at 12:05
  • I would update the answer with the latest updates from the documentation: http://masstransit-project.com/MassTransit/usage/containers/autofac.html – Chris Patterson Mar 27 '19 at 19:37