My Recommended Approach For People Who Want To Start Using Dependency Injection With C Sharp

In today's guide, I'm going to cover the way that I use dependency injection in .NET.  When I started out as a developer, terms like SOLID and designing to interfaces meant very little to me.  At the time I was writing web form projects and I didn't really see how some of these things fitted into web forms.  Fast forward a few years and moving to MVC, dependency injection has allowed me to create a lot more robust and testable solution. 

How To Get Started With Dependency Injection and C#


In terms of dependency injection, I tend to use structure map (mainly as it comes with Episerver 
and I’ve gotten used to it, rather than it’s the best DI framework).  It 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.  On most projects, you can usually get away with telling structure map to just use the default naming strategy and that’s that.  I have a more advanced guide here, to learn a little bit more about it, http://jondjones.com/learn-episerver-cms/episerver-developers-guide/episerver-best-practices-tips-and-tricks/episerver-structure-map-guide.


My Recommended Pattern To Injecting Dependencies


When you build your project with 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 details, but basically you want to follow this approach when you write new classes:

    public class MyClass
    {
        public MyClass (IDependency dependency)
        {
            Guard.ValidateObject(dependency);
        }
    }

The Guard function looks like this:

    public static class Guard
    {
        public static void ValidateObject(object objecttoTest)
        {
            if (objecttoTest == null)
            {
                throw new ArgumentException("object passed in has not been instantiated.");
            }
        }
    }

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.

Always favour constructor injection compared to ServiceLocation, Injected<> or Property injection.  You should only use this when you work with classes that won’t allow parameterless constructors, these files are generally start-up files, attributes etc…

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 different interfaces as your code base evolves.  If you need to add/remove a new dependency in an existing class that is very deep nested within other bits of code, then it can be a maintainer nightmare constantly having to refactor 4-5 classes to adding each signature to add in the new dependency.  Speaking from experience,  I’ve been given support tasks before where I’ve spent more time messing around with constructor parameters than I have fixing the bug itself.  

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 about this approach because you end up injecting more functionality than the class might need, but 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.  That interface 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 etc.. and I can ensure that my solution isn’t constantly instantiating multiple versions of the same file within the page's life cycle.  This topic's a little confusing, but you can read more about it here, http://jondjones.com/learn-episerver-cms/episerver-developers-guide/episerver-dependency-injection/episerver-dependencies-in-episerver-explained-unit-testing-part-1

submit to reddit

Jon D Jones

Software Architect, Programmer and Technologist Jon Jones is founder and CEO of London-based tech firm Digital Prompt. He has been working in the field for nearly a decade, specializing in new technologies and technical solution research in the web business. A passionate blogger by heart , speaker & consultant from England.. always on the hunt for the next challenge

Back to top