In this guide, you will learn how to apply dependency injection within .NET. When I started out as a developer, terms like SOLID and designing to an interface meant very little to me. At the time I was writing web form projects and I struggled to see how these concepts that people told me were important mattered. Fast forward a few years where the sites I build are entirely built using MVC, dependency injection makes a lot of sense. In fact, I can't think of a good reason not to use it.
How To Get Started With Dependency Injection and C
In terms of dependency injection, I tend to use Structure map as my go-to IoC framework. I use this as I mainly build websites using Episerver CMS and Episerver ships with it. The structure map is powerful and it will do everything you need it to, although the documentation could be a bit better. Structure map can be fiddly to get right, but after you go through the learning curve it’s pretty simple to use. When it comes to .NET there are loads of IoC containers available, if you do not like Structure Map that is OK. The main thing is to just pick one.
On most projects, you can usually get away with telling Structure Map to just use the default strategy. The default strategy is pretty simple if something is called IMyClass
try to automatically map it to a class called MyClass
if one exists. I have a more advanced guide here, to learn a little bit more about it, Episerver Structure Map Guide.
My Recommended Pattern To Injecting Dependencies
When you code using a test-first approach, you should be aiming to not create new objects within your classes, instead, you need to pass any dependencies via an interface into the classes constructor. There’s a good book called dependency injection in .NET that explains this process in a lot of detail, but basically, you want to follow this approach when you write new classes:
The guard function looks like this:
The guard is a way to enforce that every class in your solution gets instantiated with the correct dependencies. Ideally, for every class, you should have unit tests to test that the guards are working as expected. When using dependency injection, always favour constructor injection, compared to ServiceLocation
, or property injection. You should only use an alternative approach when you work with third-party code that won’t allow parameterless constructors for whatever reasons.
My Top Tip To Making Your Dependency Injection Code As Pain-Free As Possible
A second problem when you work with dependency injection is needing to add and remove injected paramters as your codebase evolves. If you need to add/remove a new dependency into an existing class that is very deep nested within the dependency chain, it can be a maintenance nightmare constantly having to refactor 4-5 classes to adding each signature to add in the new dependency. If you have a lot of parameter validation based tests then you can spend a lot of time fixing things! Speaking from my personal experience, I’ve been given support tasks that have taken me more effort to refactor the unit tests than making the change request!
To combat this need of constant changing constructor signature, I tend to favour an approach where I pass in one global dependency that’s simply a container to the rest of the dependencies required. Some people frown on this approach. Being a purist, you should only ever pass in the dependencies you need. You end up injecting more functionality than the class might need, however, in terms of making your life easy and enjoyable, this is the approach I recommend.
Using this approach cuts down on a lot of duplicate code and a lot of maintainer woes. On most projects, I create a dependency called IWebsiteDependencies
. This class has a reference to all the other useful dependencies the site needs to use. In this way, I can inject a single parameter into my constructor. In my WebsiteDependencies
class. I can do all the guard checking within this single class, avoiding having to do it somewhere else.
This topic's a little confusing, but you can read more about it here, Dependencies In Episerver Explained - Unit Testing Part 1. Happy Coding 🤘