Tag Archives: Dependency Injection
Dependency Injection Patterns

Motivation

I’ve seen several different approaches to Dependency Injection, each of which have their own strengths and weaknesses. I run an internship program in which I teach these patterns to college students. I believe each pattern and anti-pattern has its pros and cons, but my observation is that even experienced devs haven’t fully articulated the cost-benefit of each approach to themselves. This is my attempt to do that.

Property Injection

“Property Injection” or “Setter Injection” refers to the process of assigning dependencies to an object through a Property or Setter method.

Example


public class Widget { public Bar Bar {get; set; } public void Foo(string someValue) { Bar.SomeMethod(someValue); } }

There are pros and cons to this approach.

Pros

  • Enables easy faking for test purposes.
  • Keeps method signatures tidy.
  • Dependencies are clearly specified if you are looking at the class.

Cons

  • Temporal Dependency

What is a temporal dependency? Perhaps it’s best to illustrate with an example. Here is my first attempt at using the class as defined above.

    var widget = new Widget();
    widget.Foo("Hello World!");

Did you spot the problem? I never set Bar. When I attempt to call Foo I’ll get the oh-so-helpful NullReferenceException. I find out after I try to use the class that I have a missing dependency. I have to open the class to find out which dependency is missing. Then I have to modify my code as follows:

var widget = new Widget();
widget.Bar = new Bar();
widget.Foo("Hello World!");

It’s called a temporal dependency because I have to set it before I can call any methods on the class. What’s worse, the API of the class doesn’t give me any indication that anything is wrong until after I attempt to run it.

Method Injection

“Method Injection” refers to passing dependencies to the method that uses them.

Example


public class Widget { public void Foo(Bar bar, string someValue) { // snipped } }

Pros

  • No temporal dependencies
  • dependencies are clearly communicated via the API
  • Easily replace dependencies with fakes for testing purposes

Cons

  • Method signature explosion
  • Method signature fragility
  • Clients have to concern themselves with the classes dependencies

What are method signature explosion and fragility? Method Signature Explosion means that arguments to my method signatures will increase as dependencies change. This leads to Method Signature Fragility which means that as dependencies change, clients of the method have to change as well. In other words, we lose the benefit of encapsulated logic.

Constructor Injection

Constructor Injection is the process of making dependencies available to a class through its constructor.

Example


public class Widget { private Bar _bar; public Widget(Bar bar) { _bar = bar; } public void Foo(string someValue) { _bar.SomeMethod(someValue); } }

Pros

  • Enables easy faking for test purposes.
  • Keeps method signatures tidy.
  • Dependencies are clearly specified through the API
  • No temporal dependencies
  • No Method Signature Explosion
  • No Method Signature Fragility

Cons

  • none – other than those inherent to the nature of using Dependency Injection in the first place.

Of the three approaches listed so far, I strongly prefer Constructor Injection. I see nothing but benefits in this approach.

Lazy Injection

If you’re getting started with Dependency Injection, I strongly recommend researching a Dependency Injection Framework such as Ninject to make constructing your class hierarchies easy. If you’re not ready to bite that off you might consider using Lazy Injection. This is a technique by which your constructor arguments are given default values so that you can instantiate your class with all of your default system values at run-time, but pass fakes during test-time.

Example


public class Widget { private Bar _bar; public Widget(Bar bar = new Bar()) { _bar = bar; } public void Foo(string someValue) { _bar.SomeMethod(someValue); } }

You can do this with Property Injection as well, mitigating some of the cons of that approach. You are still left opening the class to figure out how and what to fake however.

Example


public class Widget { public Bar Bar {get; set; } public class Widget() { Bar = new Bar(); } public void Foo(string someValue) { Bar.SomeMethod(someValue); } }

Service Locator

Service Locator is widely considered to be an anti-pattern. To understand why, read “ServiceLocator is an Anti-Pattern“.
Service Locator involves making an open-ended registry of dependencies widely available to any class that wants them.

Example


public class Widget { public Bar Bar {get; private set; } public class Widget() { Bar = ServiceLocator.Get<Bar>(); } public void Foo(string someValue) { Bar.SomeMethod(someValue); } }

On the surface this looks awesome.

Pros

  • Keeps method signatures tidy.
  • No temporal dependencies
  • No Method Signature Explosion
  • No Method Signature Fragility

Cons

  • Dependencies are not clearly specified through the API
  • Because my API doesn’t communicate my dependencies, I have to understand the classes’ implementation details to properly test it.
  • It encourages dependency explosion inside the class. This is another way of saying that a class with too many constructor arguments is a “smell” and I lose the benefit of being confronted with that “smell” if I use ServiceLocator.

Despite these flaws, it is sometimes useful as a scaffolding mechanism to introduce a Dependency Injection Framework into an application that was not designed with Dependency Injection in mind. I want to stress that I believe this pattern should only be used as an interim step on the road to full Dependency Injection Framework support in legacy applications. You should make it a point to remove ServiceLocator as quickly as possible after introducing it.

Closing Thoughts

These patterns are by no means exhaustive, but they are the common one’s I’ve seen over the years.

If you are using a Dependency Injection Framework (my favorite is Ninject), some of the cons of these approaches may be mitigated by the Framework. This may change the equation with respect to which method is appropriate for your use-case.

Testing Ninject Bindings

I recently had a subtle production bug introduced by creating more than one Ninject binding for a given interface to the same instance.

I wanted to be able to see what bindings existed for a given interface, but Ninject does not provide an easy way to do that.

This gist contains an extension method I wrote (with the help of a StackOverflow article) to acquire this information.

As this code relies on using reflection to get a private member variable, this code is brittle in the face of a change in the implementation of KernelBase. In the meantime, it works on my machine.

Announcing the Yodelay .NET Framework Extensions Project

I have created an open-source project on CodePlex called “Yodelay”. From the project description:

The Yodelay .NET Framework Extensions project provides a library of components that make many kinds of programming tasks simpler. These include basic MVVM components, Unit Test Extensions, and a poor-man’s Dependency Injection library.

Most of the classes and extension methods in this library are rei-mplementations or adaptations of components I have written in other places. Some of them have been found in various forms on developer blogs. Where this is true, I have indicated where I retrieved the original source code in the comments. This library is not just a collection of random classes. The attempt here is to bring all of these components together and use them in an integrated fashion to develop stable applications faster.

Not all code in this project is currently covered by unit tests. This is because many of the classes were adapted from blogs or other existing projects and may not have been developed using TDD. Every effort will be made to bring existing classes under test coverage, and to practice TDD when adding new code.

Why did I call it Yodelay? For no other reason than I like the way the word sounds. It rolls off the tongue easily, which is the effect I hope the library has on applications.

There is no installer yet. Yodelay is in version 0.1, but there are already quite a few goodies in the library. Everything is built against the 4.0 framework. I will try to work on it a little each week, adding new components and demo projects when I can. In the near future I will be signing the assemblies and building an installer for them.

Enjoy!