Asp.NET Core Dependency Injection Integration

Component: NServiceBus
NuGet Package NServiceBus (7-pre)
This page targets a pre-release version and is subject to change prior to the final release.

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.

It is possible to use an external container to satisfy both requirements.

While this sample illustrates the scenario using Autofac, the same can be achieved by using most other DI libraries. Using Autofac requires adding reference to the Autofac.Extensions.DependencyInjection package.

Configuring to use shared DI

public IServiceProvider ConfigureServices(IServiceCollection services)
{
    var builder = new ContainerBuilder();

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

    IEndpointInstance endpoint = null;
    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 will be used by the infrastructure to resolve components. The same container instance is shared with the NServiceBus endpoint.

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

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;
    }
}

Related Articles


Last modified