Search code examples
c#masstransit

MassTransit automatically add consumers


Im using MassTransit to connect to our RabbitMQ. Currently im working on generalizing the code over the 15 solution that uses it. But i hit road block on the setup part. Original it looked like this:

  services.AddMassTransit(c =>
            {
                c.AddConsumer<MoveMouldConsumer>();
                c.AddBus(provider => Bus.Factory.CreateUsingRabbitMq(cfg =>
                {
                    cfg.UseHealthCheck(provider);
                    cfg.Host(MassTransitHelper.CreateRabbitMQEndpointUri(messageQueueSettings), h =>
                    {
                        h.Username(messageQueueSettings.Username);
                        h.Password(messageQueueSettings.Password);
                    });

                    cfg.PrefetchCount = (ushort) messageQueueSettings.PrefetchCount;
                    cfg.MessageTopology.SetEntityNameFormatter(new EntityNameFormatter());
                    cfg.ExchangeType = ExchangeType.Direct;
                    
                    cfg.ReceiveEndpoint(NameFormatter.FormatQueueName<MouldMovementEvent>("serviceName"), e =>
                    {
                        e.Bind(NameFormatter.FormatExchangeName<MouldMovementEvent>()); //Bind to Exchange
                        e.UseMessageRetry(r => r.Incremental(5, 5.Seconds(), 10.Seconds()));
                        e.ExclusiveConsumer = false;
                        e.PrefetchCount = messageQueueSettings.PrefetchCount;
                        e.Consumer<MoveMouldConsumer>(provider);
                        e.UseCircuitBreaker(cb =>
                        {
                            cb.TripThreshold = 15;
                            cb.ActiveThreshold = 10;
                            cb.ResetInterval = 5.Minutes();
                        });
                    });
                }));
            });

I have so far managed to generalize it to this:

services.AddMassTransit(c =>
            {
                c.AddConsumer<MoveMouldConsumer>();
                c.AddBus(provider => Bus.Factory.CreateUsingRabbitMq(cfg =>
                {
                    cfg.UseHealthCheck(provider);
                    MassTransitSetup.BasicSetup(cfg, messageQueueSettings);
                    MassTransitSetup.InitializeConsumer<MouldMovementEvent, MoveMouldConsumer>(cfg, messageQueueSettings, provider, 5, "report");
                }));
            }); 

But the part im missing is that i like to be able to automatically add all consumers by getting from Assemblies which i do like so:

var types = AppDomain.CurrentDomain.GetAssemblies()
            .SelectMany(s => s.GetTypes())
            .Where(p => typeof(IConsumer).IsAssignableFrom(p) && p.IsClass && !p.IsAbstract && p.Namespace!.Contains("MST.Hepper.")).ToList();

But my problem is how to iterate through and add the c.AddConsumer<>(); or MassTransitSetup.InitializeConsumer<,>


Solution

  • Just add an extra Select() to get assemblies implementing an empty marker interface example IMessageMarker like so:

     var assemblies = AppDomain.CurrentDomain.GetAssemblies()
                      .SelectMany(s => s.GetTypes())
                       // A marker
                      .Where(p => typeof(IMessageMarker).IsAssignableFrom(p) && p.IsClass && 
                        !p.IsAbstract && p.Namespace!.Contains("MST.Hepper."))
                      .Select(x => x.Assembly) // Get assembly
                      .ToArray();
    // elided...
     c.AddConsumer(assemblies);