Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to initialize scoped dependencies for consumers using MassTransit filters?

I would like to initialize some dependencies resolved from the MassTransit serviceProvider in the same way Asp.Net Core does with the pipeline's middlewares.

In particular I would like to inspect the incoming message before the consumer is called and extract the tenant from it (I'm currently working on a multitenant web application with single database per tenant).

With this informations I need to initialize some scoped instances (Ef Core DbContext for example).

I know that I can inject them in the Consumer through constructor but this means that I must do that everytime I write a new one, so I suppose that a filter should be the right place (correct me if I'm wrong).

The problem raises when I need to access the current consumer scope to resolve the dependencies that I need. I was thinking that the behavior of the MassTransit' pipeline was similar to the Asp.Net one regarding middleware injection but I was probably wrong.

I haven't found any documentation on how to do that clearly without cluttering the code of the filter, so any suggestion is going to be really appreciated.

This is the filter that I need to modify:

public class TenantContextInitializerFilter<T> : IFilter<T> where T : class, ConsumeContext
{
    public void Probe(ProbeContext context) { }

    public async Task Send(T context, IPipe<T> next)
    {
        //Resolve scoped instance here and do something before Consumer is called
        var connectionStringProvider =  scope.GetService<IConnectionStringProvider>();

        await next.Send(context);
    }
}


public class RegistrationsDeliveredEventConsumer : IConsumer<IRegistrationsDelivered>
{
    private readonly IConnectionStringProvider _connectionStringProvider;

    public RegistrationsDeliveredEventConsumer(IConnectionStringProvider connectionStringProvider)
    {
        //This should be the same instance that has been resolved in the filter' Send() method
        _connectionStringProvider = connectionStringProvider;
    }

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

    }
}

This is a simplified example of my code but this should be enough

like image 570
Brando Caserotti Avatar asked Dec 05 '25 05:12

Brando Caserotti


1 Answers

There's two facets to consider: 1) are filters registered as services/pulled from the service collection when using the ASP.NET Core integration and 2) what lifetime do the filters have if they are. I'm not familiar with the MassTransit ASP.NET Core integration, but it looks like you should be good based on a cursory review. You'll need to confirm that both of those requirements are met.

For dependency injection, in general, constructor injection is the way to go unless there's a very specific need to do something different, which does not seem to be the case here. In short, you need a constructor for your filter.

What exactly you need to inject is a function of the lifetime of the filter. If it has a transient lifetime, then you can inject your scoped dependencies directly. If it has a singleton lifetime, then you'll need to inject IServiceProvider instead, and do the following whenever you need to use one of those dependencies:

using (var scope = _serviceProvider.CreateScope())
{
    var dep = scope.ServiceProvider.GetRequiredService<MyDependency>();
    // do something with `dep`
}
like image 156
Chris Pratt Avatar answered Dec 07 '25 19:12

Chris Pratt



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!