In this tutorial, you will learn how to use dependency injection with Umbraco 8. In Umbraco v7 and below, the approach to use a core helper was via a global singleton based static helper like this:
Umbraco re-jigged its architecture so it is now a more testable and flexible solution. This was done by moving away from the singleton approach and adopting dependency injection. When you install Umbraco v8, you will get an IoC/DI container out of the box. As everything required to use dependency injection is pre-configured for you on installation and boot up, there really are no excuses to not use dependency injection when you are writing custom code. Using dependency injection within v8 is really simple and in this guide, I will show you everything that you need to do. Sounds good? Read on!
The Dependency Injection Problem
To use dependency injection you will want to write custom code that works to an interface. Below shows a simple example that would allow us to use dependency injection within our codebase. We define a class and expose its only method from an interface:
To use dependency injection you would pass the interface as an argument into some code. In Umbraco, the starting path for most code is a controller. In most cases instances the starting point to inject your interfaces will be a controller, which is done like this:
If you tried to run this code as-is, the page would fail to load and an exception will be thrown. The exception message will be in the format of System.InvalidOperationException: Unable to resolve type: ....
. The reason why an exception gets thrown is that the IoC container that Umbraco ships with, simple injector, does not know how to map ICustomCode
to the CustomCode
class. To fix this, you will need to tell Umbraco how this mapping should work. You need to register your dependency with the DI container. This is done using a composer.
Composer
In Umbraco V8 the concept of a component and a composer was introduced. Components are the new way to hook into the Umbraco pipeline and register your own custom functionality. In this article, I'm only going to focus on the component to register custom dependencies. It is worth noting that this approach can be used for things like registering custom events etc...
The component that needs to be registered to do dependency injection within Umbraco is the IUserComposer
. To register your own dependencies, you will need to create a class that implements IUserComposer
. On initial-load Umbraco uses reflection to check for any classes that implement IUserComposer
. If it finds any, it will run the class and register any dependencies within it. To get the example above to work the ICustomCode
needs to be registered.
When registering your own custom dependency you should also be aware of the different lifecycle requests:
As you can see there are different types of scope you can use to register your type. In most cases stick with Transient
. This will make your life easier. Transient
will create a new instance whenever a dependency is requested. Avoid single except on maybe classes that deal with caching. You can get some funky bugs if you get this stuff wrong, so sticking with Transient
will prevent this. Happy coding!