ASP.NET Core Dependency Injection Integration

Component: NServiceBus
NuGet Package NServiceBus (7.x)

ASP.NET Core comes with an integrated dependency injection (DI) feature. When hosting NServiceBus endpoints inside an Asp.NET Core app, components registered for DI might need to be shared between ASP.NET components and NServiceBus message handlers.

Configuring an endpoint to use built-in DI

Using this sample requires adding reference to the NServiceBus.MSDependencyInjection community package.
public void ConfigureServices(IServiceCollection services)
{
    services.AddLogging(loggingBuilder => loggingBuilder.AddConsole());
    services.AddSingleton(sp => endpoint);
    services.AddSingleton<MyService>();

    var endpointConfiguration = new EndpointConfiguration("Sample.Core");
    endpointConfiguration.UseTransport<LearningTransport>();
    endpointConfiguration.UseContainer<ServicesBuilder>(
        customizations: customizations =>
        {
            customizations.ExistingServices(services);
        });

    endpoint = Endpoint.Start(endpointConfiguration).GetAwaiter().GetResult();
}

When the sample is run, a web application is started. All web requests received will trigger a message send operation:

applicationBuilder.Run(
    handler: context =>
    {
        if (context.Request.Path != "/")
        {
            // only handle requests at the root
            return Task.CompletedTask;
        }
        var applicationServices = applicationBuilder.ApplicationServices;
        var endpointInstance = applicationServices.GetService<IEndpointInstance>();
        var myMessage = new MyMessage();

        return Task.WhenAll(
            endpointInstance.SendLocal(myMessage),
            context.Response.WriteAsync("Message sent"));
    });

Message handlers will have dependencies injected at runtime by the configured Inversion of Control container:

public class MyHandler :
    IHandleMessages<MyMessage>
{
    MyService myService;

    public MyHandler(MyService myService)
    {
        this.myService = myService;
    }

    public Task Handle(MyMessage message, IMessageHandlerContext context)
    {
        myService.WriteHello();
        return Task.CompletedTask;
    }
}

Configuring to use shared DI with Autofac

It is also possible to use an external container to share components between ASP.NET and NServiceBus message handlers.

While this sample illustrates the scenario using Autofac, the same can be achieved by using other DI libraries. Using Autofac requires adding reference to the Autofac.Extensions.DependencyInjection package.
public IServiceProvider ConfigureServices(IServiceCollection services)
{
    services.AddLogging(loggingBuilder => loggingBuilder.AddConsole());

    var builder = new ContainerBuilder();

    builder.Populate(services);
    builder.RegisterInstance(new MyService());

    builder.Register(c => endpoint)
        .As<IEndpointInstance>()
        .SingleInstance();

    var container = builder.Build();

    var endpointConfiguration = new EndpointConfiguration("Sample.Core");
    endpointConfiguration.UseTransport<LearningTransport>();
    endpointConfiguration.UseContainer<AutofacBuilder>(
        customizations: customizations =>
        {
            customizations.ExistingLifetimeScope(container);
        });

    endpoint = Endpoint.Start(endpointConfiguration).GetAwaiter().GetResult();

    return new AutofacServiceProvider(container);
}

The ConfigureServices method is called by .NET Core infrastructure at application startup time and returns a IServiceProvider instance that is used by the infrastructure to resolve components. The same container instance is shared with the NServiceBus endpoint.

Related Articles


Last modified