NServiceBus supports two modes of operation for containers, internally managed and externally managed. NServiceBus uses Microsoft.Extensions.DependencyInjection (MS.DI) as the default recommended dependency injection container.
For most scenarios, use the built-in MS.DI container. Only use a third-party container if you require features not available in MS.DI.
NServiceBus automatically registers and invokes message handlers, sagas, and other user-provided extension points using a dependency injection container.
Modes of operation
NServiceBus supports two modes for dependency injection:
- Internally managed: NServiceBus manages the container lifecycle as part of the endpoint lifecycle.
- Externally managed: The application or host provides and controls the container lifecycle.
Understanding the different modes is only required in custom hosting scenarios or when using third-party container integrations. Applications using the generic host or the web application builder should leverage NServiceBus.Extensions.Hosting which takes care of the necessary plumbing automatically.
Internally managed mode
NServiceBus creates and manages the IServiceCollection
and IServiceProvider
including proper disposal. Register your services using the standard MS.DI API exposed over the RegisterComponents
API on the endpoint configuration:
endpointConfiguration.RegisterComponents(services =>
{
services.AddTransient<MyService>();
services.AddScoped<MyScopedService>();
services.AddSingleton<MySingletonService>();
});
See MS.DI lifetimes and service registrations for more details.
The internally managed mode is intended to be used in scenarios where the NServiceBus endpoint is the entry point of the application or where multiple endpoints are hosted within the same application and each endpoint requires an isolated container instance.
Externally managed mode
Every NServiceBus endpoint requires its own dependency injection container. Sharing containers across multiple endpoints results in conflicting registrations and might cause incorrect behavior or runtime errors.
If full control over the container, including its lifetime and disposal, is needed, use externally managed mode:
During the registration phase, an instance of IServiceCollection
is passed to the EndpointWithExternallyManagedContainer.
method. The following snippets show how to use Microsoft's default implementation from the Microsoft.
NuGet package:
IServiceCollection serviceCollection = new ServiceCollection();
var startableEndpoint = EndpointWithExternallyManagedContainer.Create(endpointConfiguration, serviceCollection);
Later, during the resolution phase, the Start
method requires an instance of IServiceProvider
.
IServiceProvider builder = serviceCollection.BuildServiceProvider();
var startedEndpoint = await startableEndpoint.Start(builder);
Refer to the container's documentation on how to use the container with the Microsoft.
API.
The externally managed mode is intended to be used in scenarios where the NServiceBus endpoint integrates into an existing application or host already using either MS.DI or using a third party container that supports integration with MS.DI.
Property injection
Property injection is not supported by default with MS.DI. Use constructor injection for all dependencies. If you require property injection, refer to your container's documentation.
Using third-party containers
If features are needed that are not available in MS.DI, it is possible to integrate a third-party container that supports the MS.DI abstractions. See Externally managed mode on how to use the externally managed mode to seperate the registration phase from the resolving phase on the container and consult the third-party container documentation on how to integrate the container into MS.DI.
The NServiceBus Version 7 to 8 upgrade guide also contains snippets hinting at the custom configuration potentially required to integrate with Autofac, Lamar, Unity, StructureMap, Castle Windows, or Spring.
For leveraging third-party containers with NServiceBus.
, refer to the configure custom containers documentation for further details.
Service registrations
Custom services may be registered using the IServiceCollection
API.
Instance per call
A new instance will be returned for each call.
Represented by the enum value ServiceLifetime.
.
endpointConfiguration.RegisterComponents(
registration: configureComponents =>
{
configureComponents.AddTransient<MyService>();
});
or using a delegate:
endpointConfiguration.RegisterComponents(
registration: configureComponents =>
{
configureComponents.AddTransient(serviceProvider => new MyService());
});
Instance per unit of work
The instance will be a singleton for the duration of the unit of work. In practice this means the processing of a single transport message.
Represented by the enum value ServiceLifetime.
.
endpointConfiguration.RegisterComponents(
registration: configureComponents =>
{
configureComponents.AddScoped<MyService>();
});
or using a delegate:
endpointConfiguration.RegisterComponents(
registration: configureComponents =>
{
configureComponents.AddScoped(serviceProvider => new MyService());
});
Single instance
The same instance will be returned each time.
Represented by the enum value ServiceLifetime.
.
Singleton
components with dependencies that are scoped Transient
or Scoped
will still resolve. In effect, these dependencies, while not scoped as Singleton
, will behave as if they are Singleton
because the instances will exist inside the parent component.
endpointConfiguration.RegisterComponents(
registration: configureComponents =>
{
configureComponents.AddSingleton<MyService>();
});
or using a delegate:
endpointConfiguration.RegisterComponents(
registration: configureComponents =>
{
configureComponents.AddSingleton(serviceProvider => new MyService());
});
Injecting the message session
IMessageSession
is not registered automatically in the container and must be registered explicitly to be injected. Access to the session is provided via IStartableEndpointWithExternallyManagedContainer.
The session is only valid for use after the endpoint have been started, so it is provided as Lazy
.
The NServiceBus.Extensions.DependencyInjection Usage sample demonstrates how to register the message session.
Resolving dependencies
It is recommended to follow the dependency injection guidelines for .NET. Be aware of the following special cases with NServiceBus: