NServiceBus now supports Microsoft Extensions DependencyInjection
The history of dependency injection (DI) containers in .NET is almost as long as .NET itself. StructureMap and Castle Windsor were released in 2004, Spring.NET in 2005, and more after that, each with their own unique API, some more opinionated than others.
And yet each of these libraries fulfills a fairly simple task: a place to hold on to dependencies so that objects can get them when they need them.
With .NET Core, Microsoft has created a DI container abstraction that is quickly becoming a de facto standard: Microsoft.Extensions.DependencyInjection.
NServiceBus now supports this same container abstraction via our new NServiceBus.Extensions.DependencyInjection package, which means you can use any container that conforms to the Microsoft abstraction with NServiceBus. This has a ton of advantages, but also means the time has come to retire our existing container adapters.
🔗A common abstraction
The new Microsoft container abstraction provides a common abstraction that all container authors can conform to. But what does that really mean?
For the most part, we don’t care what container you use, as long as you’re happy with it. We don’t want to be a blocker to you using the container of your choice…except many times, that’s exactly what happens.
For example, in order to support Autofac, we have an NServiceBus.Autofac package that acts as an adapter between NServiceBus and Autofac. We have similar packages for CastleWindsor, Ninject, Spring, StructureMap, and Unity.
So when Autofac ships a new major version…you can’t use it with NServiceBus! At least, not until we release a new version of our NServiceBus.Autofac adapter package, which we aren’t always able to do quickly. Not that we don’t want to, but like everyone else, we have a limited staff of engineers and have to prioritize what we work on.
But thanks to the widespread adoption of the new Microsoft abstraction, when Autofac 5.0 was released, there was also a release of Autofac.Extensions.DependencyInjection on the same day.
With the common abstraction and implementations provided by the container authors, you aren’t dependent upon us to upgrade your container version. When a new version is released, you can upgrade immediately…or not. It’s completely up to you.
🔗More choices
Now that NServiceBus supports the Microsoft container abstraction, that means you don’t have to be limited to the container adapters we’ve previously supported.
Previously-supported containers that can now be used via the Microsoft container abstraction include:
- Autofac via Autofac.Extensions.DependencyInjection
- Castle Windsor via Castle.Windsor.MsDependencyInjection
- Unity via Unity.Microsoft.DependencyInjection
- StructureMap via StructureMap.Microsoft.DependencyInjection
In addition to these, at the time of this writing you can also use the following containers which have never had a Particular-supplied adapter package:
- Lamar (the successor to StructureMap) via Lamar.Microsoft.DependencyInjection
- Dryloc via DryIoc.Microsoft.DependencyInjection
- Grace via Grace.DependencyInjection.Extensions
- LightInject via LightInject.Microsoft.DependencyInjection
- Stashbox via Stashbox.Extensions.Dependencyinjection
And all of these packages should work great with the .NET Generic Host making them easy to use in all your .NET Core applications, including with NServiceBus.
🔗Moving forward
Using the Microsoft abstraction gives our customers so much more freedom and choice that we’ve realized the time has come for those old adapter packages to be retired.
We’ve released new minor versions of the following packages, which obsoletes the adapter API with a warning:
- NServiceBus.Autofac
- NServiceBus.CastleWindsor
- NServiceBus.Unity
- NServiceBus.StructureMap
We will continue fix bugs in these packages according to our support policy, but the next major version (which we would likely release whenever we release NServiceBus 8.0) will mark the API as obsolete with a build error, prompting you to switch to the Microsoft abstraction.
If you’re using one of these packages, you have three choices:
- Continue using your existing version of your container adapter, and do not upgrade to the newest version that includes the deprecated API.
- Upgrade to the minor version, and let the build warning serve as a TODO for later. (This is not an option if your project uses the
TreatWarningsAsErrors
project property.) - Use the NServiceBus.Extensions.DependencyInjection package along with the adapter package provided by your container of choice.
Unfortunately, there are a couple of containers that do not support the new abstraction:
- Ninject, at the time of this writing, has decided not to provide an adapter.
- Spring.NET does not currently support .NET Core, which means it cannot support the Microsoft abstraction either.
Since there is no clear upgrade strategy for these containers, we aren’t taking the step of deprecating those packages yet. However, it’s very unlikely that we would release new versions of these packages for a new major version of NServiceBus, and we may decide to add compile warnings to the packages in the future (as we have with the other packages) in order to guide users toward something else.
Ultimately, the choice of how to proceed is up to you.
🔗Summary
With support for the new Microsoft dependency injection abstraction (say that three times fast), we’ve removed ourselves from the DI equation. That means you now have a much wider choice of DI containers to use, and the freedom to upgrade them whenever it makes sense for you.
Effectively, we’ve gotten ourselves out of the way, so now you can do what you need to do.
Most of the existing NServiceBus container adapters can be replaced with the new package and the adapter provided by the container author.
To see how this is done, check out the documentation for the new NServiceBus.Extensions.DependencyInjection package, the generic sample, or one of our newly updated container-specific samples:
About the author: Sean Feldman is a generalist at Particular Software who can appreciate simple and elegant code, as well as how much work it takes to create and maintain that simplicity.