Implementing Dependency Injection in Sitecore

There are a few different ways to implement dependency injection in Sitecore. Once upon a time, the only way to implementing DI was to use third-party libraries like Simple Injector. Since Sitecore 8.2 release, Sitecore includes build in dependency injection based on Microsoft’s Dependency Injection for ASP.NET Core. We can still use third-party modules for DI in the latest Sitecore and it is still a valid option with a few benefits over the out-of-the box DI solutions.

Choosing approach can be daunting. At the end of the day, whatever solution you implement is going to work. Just pick whatever feels right for the solution you are working on. Recently, I implemented DI in Sitecore 8.2 with the out-of-box Sitecore Dependency Injection. The reason for this choice is:

  • Sitecore is already using it. For that reason, it will be supported by Sitecore. All we need to do is to register our custom configurator.
  • We did not need to add extra third-party module dependency to the existing solution.
  • The performance is said to be as fast as the best performing third-party DI containers, like Simple Injector.
  • Habitat implements it. All I needed to do is to take the example code and implement it in the existing solution. Although the solution is for Sitecore 9, it works for 8.2.
  • The DI container is referenced from the composition root with this solution (see details for this fantastic blog post).
  • I implemented DI in an already matured Sitecore code base. Habitat implementation has the minimum disruption to the existing solution and allowed us to introduce DI slowly to the entire code base.

When I implemented DI, I started with implementing it in a Feature project for my own humble Sitecore that I installed on my laptop for learning. There are heaps of posts that help you to implement DI in the real-world solution. This post gives you the example of implementing DI at a project level just to understand how it works.

This is fairly quick and simple. But, I promise this is a fun and satisfying activity. Let’s get started.

Aim

In the previous post, we created a controller depending on repository. The dependency injection is done in the constructor. We want to register FrontEndTestController and FrontEndTestRepository in the DI container so that we can get rid of the line injecting the concrete implementation.

At the end of this post, the poor man’s DI will be gone for good!

Steps

(1) Add dlls for Microsoft DI

We need to add two dlls for the project (in this example, SitecoreDev.Feature.Design). These dlls come with the software installation. I suggest to copy & paste from the web root bin directory and move them to the code base lib folder.

  • Extensitons.DependencyInjection
  • Extensions.DependencyInjection.Abstractions.

(2) Register dependencies

Create RegisterDependencies.cs and register dependencies manually as below.

(3) Register service

Create a config file Feature.Design.config in App_Config/Include. This will allow Sitecore to register dependencies.

(4) Remove the poor man’s DI constructor

We can now remove the constructor instantiating the actual implementation.

That’s it. You can also check the container registration from http://[instance]/sitecore/admin/showservicesconfig.aspx.

Next Steps

Now that you know how this works, all you need to do is to register dependencies when the application starts through Sitecore pipeline. Here are the steps I took.

  • Create a DependencyInjection project in Foundation and move the entire code from Habitat solution here.
  • Cleaned up ServiceCollectionExtensions methods (removed unnecessary methods and turned unnecessary public methods to privates).
  • Added Scoped into Lifetime enum and ServiceCollectionExtensions methods for full lifetime management support.
  • Wrote unit tests on ServiceCollectionExtensions.
  • Added dependency registration attributes (as described here) to a few classes and implemented in one controller to start with.

Now, it’s your turn to implement DI in your Sitecore solutions.

References

There are so many wonderful references that we can use. Here are the ones I recommend you to read.

Front-End
TypeScript: type aliases to check type equality

This post is to analyse how the type equality check by using type aliases proposed by Matt Pocock in his twitter post. These type aliases allow us to elegantly express type equality checks in unit tests. All we need to do is to pass the output and expected types in …

Front-End
Fixing it.only type error in Jest

If you are getting a type error with it.only in Jest, it could be due to incorrect TypeScript typings or incompatible versions of Jest and TypeScript. To resolve this issue, you can try the following steps: Make sure you have the latest versions of Jest and its TypeScript typings installed …

Front-End
yup conditional validation example

Here’s an example of a Yup validation logic where the first input field is optional but, if filled, it must contain only alphabetic characters, and the second input field is required: import * as Yup from “yup”; const validationSchema = Yup.object().shape({ firstField: Yup.string().matches(/^[A-Za-z]*$/, { message: “First field must contain only …