This is part of the NServiceBus Upgrade Guide from Version 7 to 8, which also includes the following individual upgrade guides for specific components:
Feature Details
- Upgrading the data bus from version 7 to 8
- Dependency Injection changes
- Upgrade NServiceBus downstreams from Version 7 to 8
- Upgrading message contracts from Version 7 to 8
- Upgrade NServiceBus pipeline extensions from Version 7 to 8
- Transport configuration changes
Transports
- AmazonSQS Transport Upgrade Version 5 to 6
- Azure Service Bus Transport Upgrade Version 2 to 3
- Azure Storage Queues Transport Upgrade Version 10 to 11
- MSMQ Transport Upgrade Version 1 to 2
- MSMQ Transport Upgrade Version 2 to 2.0.4
- RabbitMQ Transport Upgrade Version 7 to 8
- SQL Server Transport Upgrade Version 6 to 7
Persistence
- Cosmos DB Persistence Upgrade from 1 to 2
- NHibernate Persistence Upgrade Version 8 to 9
- RavenDB Persistence Upgrade from 7 to 8
- SQL Persistence Upgrade Version 6 to 7
Hosting
Other
NServiceBus no longer provides adapters for external dependency injection containers. Instead, NServiceBus version 8 provides the ability to use any container that conforms to the Microsoft.
abstraction.
The following adapter packages will no longer be provided:
Instead of the container adapter packages, use the NServiceBus.Extensions.Hosting package. To use a third party dependency injection container refer to the externally managed container mode. See the migrating to the Generic Host or migrating to externally managed mode sections for further information.
Behavioral changes
The behavior has been aligned with the expectations of the Microsoft.
package. The following changes have been introduced:
- The same component can be registered multiple times
- The last registration of the same component wins
Property injection
Property injection is not covered by Microsoft.
. Therefore, the NServiceBus default dependency injection container no longer supports property injection. Property injection might still be supported by the third party containers.
UseContainer is deprecated
The UseContainer
API to integrate third party containers with NServiceBus has been removed as it does not align with the Microsoft.
model. To use a custom dependency injection container with NServiceBus, use the externally managed container mode.
RegisterComponents changes
The EndpointConfiguration.
API now provides access to the underlying IServiceCollection
. The registration methods formerly provided by IConfigureComponents
are available as extension methods to simplify migration. However, it is recommended to use the official IServiceCollection
registration API instead.
NServiceBus DependencyLifecycle
maps directly to ServiceDescriptor ServiceLifetime
:
DependencyLifecycle | ServiceLifetime |
---|---|
InstancePerCall | Transient |
SingleInstance | Singleton |
InstancePerUnitOfWork | Scoped |
For example, this statement:
endpointConfiguration.RegisterComponents(s =>
s.ConfigureComponent<MyService>(DependencyLifecyle.InstancePerCall));
may be replaced with:
endpointConfiguration.RegisterComponents(s => s.AddTransient<MyService>());
See the following table for recommended replacements. See the IServiceCollection documentation for a full list of available registration methods.
ConfigureComponents usage | Replacement |
---|---|
ConfigureComponent | AddTransient |
ConfigureComponent | AddSingleton |
ConfigureComponent | AddScoped |
The former ConfigureComponents
would automatically register all interfaces of a given type. The IServiceCollection.
method, however, would not do this and all the inherited interfaces must be registered explicitly. The registrations may be forwarded to the inheriting type, for example:
endpointConfiguration.RegisterComponents(s => {
s.AddSingleton<MyService>(); // MyService implements both IServiceA and IServiceB interfaces
s.AddSingleton<IServiceA>(serviceProvider => serviceProvider.GetService<MyService>());
s.AddSingleton<IServiceB>(serviceProvider => serviceProvider.GetService<MyService>());
});
Microsoft Generic Host
NServiceBus integrates with the Microsoft Generic Host and automatically uses the host's managed dependency injection container. Most third party dependency injection containers support the Generic Host.
Migrating to the Generic Host
To host NServiceBus as part of the Generic Host, install the NServiceBus.
NuGet package and refer to the documentation for further details. Refer to the container's documentation for configuration instructions. By default, the Generic Host uses the [Microsoft.Extensions.DependencyInjection] container. See the following examples on how to integrate common DI containers with the generic host. Other supported DI containers are listed in the official documentation.
Autofac
The snippet shows how to configure Autofac using the Autofac.
NuGet package:
Host.CreateDefaultBuilder(args)
.UseServiceProviderFactory(new AutofacServiceProviderFactory())
.UseNServiceBus(...)
...
.Build();
Lamar
The snippet shows how to configure Lamar using the Lamar.
NuGet package:
Host.CreateDefaultBuilder(args)
.UseLamar()
.UseNServiceBus(...)
...
.Build();
Unity
The snippet shows how to configure Unity using the Unity.
NuGet package:
Host.CreateDefaultBuilder(args)
.UseUnityServiceProvider()
.UseNServiceBus(...)
...
.Build();
Externally managed container mode
The externally managed container mode allows integrating third-party dependency injection containers, that conform to the Microsoft.
model, with NServiceBus via the EndpointWithExternallyManagedContainer.
API. See the following sections for examples of using common DI containers.
Migrating to externally managed mode
Microsoft.Extensions.DependencyInjection
The following snippet configures NServiceBus to use the Microsoft's default container implementation.
var serviceCollection = new ServiceCollection();
var startableEndpoint = EndpointWithExternallyManagedContainer.Create(endpointConfiguration, serviceCollection);
var endpoint = await startableEndpoint.Start(serviceCollection.BuildServiceProvider());
Autofac
The following snippet configures NServiceBus to use Autofac as its dependency injection container. This requires the Autofac.
NuGet package.
var serviceCollection = new ServiceCollection();
var startableEndpoint = EndpointWithExternallyManagedContainer.Create(endpointConfiguration, serviceCollection);
var containerBuilder = new ContainerBuilder();
containerBuilder.Populate(serviceCollection);
var autofacContainer = containerBuilder.Build();
var endpointInstance = await startableEndpoint.Start(new AutofacServiceProvider(autofacContainer));
With newer versions of Autofac the ability to update an existing container has been removed. The registration phase of the dependencies is now separate from the resolve phase.
Once a component has been resolved the container is immutable. For cases when an existing lifetime scope was passed to NServiceBus:
endpointConfiguration.UseContainer<AutofacBuilder>(
customizations: customizations =>
{
customizations.ExistingLifetimeScope(container);
});
it is recommended to either:
- Move the registrations to the start of the application or
- Avoid building the container early by passing the container builder to the various bootstrapping parts of the application or
- Use a dedicated child lifetime scope which allows accessing singletons of the root container while having dependencies managed by the service collection being "rooted" within the child scope.
StructureMap
StructureMap has been sunsetted. The maintainers recommend to use Lamar instead.
The following snippet configures NServiceBus to use StructureMap as its dependency injection container. This requires the StructureMap.
NuGet package.
var serviceCollection = new ServiceCollection();
var startableEndpoint = EndpointWithExternallyManagedContainer.Create(endpointConfiguration, serviceCollection);
var container = new Container();
container.Populate(serviceCollection);
var endpointInstance = await startableEndpoint.Start(container.GetInstance<IServiceProvider>());
Castle Windsor
The following snippet configures NServiceBus to use Castle Windsor as its dependency injection container. This requires the Castle.
NuGet package.
var serviceCollection = new ServiceCollection();
var startableEndpoint = EndpointWithExternallyManagedContainer.Create(endpointConfiguration, serviceCollection);
var container = new WindsorContainer();
var serviceProvider = WindsorRegistrationHelper.CreateServiceProvider(container, serviceCollection);
var endpointInstance = await startableEndpoint.Start(serviceProvider);
Unity
The following snippet configures NServiceBus to use Unity as its dependency injection container. This requires the Unity.
NuGet package.
var serviceCollection = new ServiceCollection();
var startableEndpoint = EndpointWithExternallyManagedContainer.Create(endpointConfiguration, serviceCollection);
var container = new UnityContainer();
var serviceProvider = container.BuildServiceProvider(serviceCollection);
var endpointInstance = await startableEndpoint.Start(serviceProvider);
Spring
The following snippet configures NServiceBus to use Spring as its dependency injection container. This requires the Spring.
NuGet package.
var serviceCollection = new ServiceCollection();
var startableEndpoint = EndpointWithExternallyManagedContainer.Create(endpointConfiguration, serviceCollection);
var applicationContext = new GenericApplicationContext();
var serviceProviderFactory = new SpringServiceProviderFactory(applicationContext);
var serviceProvider = serviceProviderFactory.CreateServiceProvider(serviceProviderFactory.CreateBuilder(serviceCollection));
var endpointInstance = await startableEndpoint.Start(serviceProvider);