Wiki

Clone wiki

dicpp / Home

This research project is dedicated to exploring an implementation of the dependency injection pattern inspired by Google Guice, but in pure C++. While it has its root as an experiment, it is being used in the development of Worklog Assistant, a JIRA time tracker which keeps it fairly active

Note: the library requires C++11.

What is Dependency Injection?

Dependency Injection is a technique for supplying all dependencies that an object requires to function. The techniques are usually automated and recursive. In many cases, you no longer need to be concerned about the ceremony of constructing objects or managing their lifetimes and can instead focus on the core application logic. As a bonus, the technique also helps code to be more testable.

What is Google Guice?

Google Guice is a Java library for dependency injection written by Google engineers. It is different from related Java libraries in that it is written in and uses only pure Java, as opposed to XML files. Listen to the talk "Big Modular Java with Guice" before reading any of the code here.

How is this different from existing C++ Dependency Injection implementations?

Roughly:

  • I wrote it
  • It does not require XML, external tools or reflection but not too intrusive
  • It is low on ceremony and high on super-happy-fun time
  • It works (note: I have only tried it, not proved it correct)

Getting around lack of reflection

Constructor injection is the most powerful form of dependency injection. That is, all dependencies needed for functioning of the object are provided in the constructor.

This means that we need to be able to reflect the constructor signature. If the constructor could be passed as a member function pointer, then we would be done. Unfortunately, it can't. So we have to either specialize a class template or use a macro for convenience. The macro should usually be enough.

You can see examples of this macro ({{{DI_CONSTRUCTOR}}}) in StockQuoteApp.hpp. The linked example below has more instances of usage.

Example

See lib/examples

Scopes

Scopes are similar to Google Guice scopes except for two key differences: * Scopes in dicpp are solely responsible for constructing objects. In Guice, scopes are responsible for constructing the objects which construct the objects (got it?). dicpp takes a simpler approach and generates the second level of abstraction for you, using a decorator pattern. * Scopes in dicpp are untyped. In practice, this is not a big deal because you are usually working on the object identity (i.e., pointer level). I would be interested to hear if the actual types matter in a scope.

See the singleton scope.

TODO

  • More tests
  • It is highly inconvenient to use annotations in constructors. Figure out a way to include the annotation in the constructor without modifying the signature.
  • Write example without DI to show the pains it solves.

I have (had?) no intention of

  • Implementing member injection ** Implemented. See injected_member.hpp or test_injected_member.cpp
  • Implementing setter injection
  • Supporting multiple constructors ** Actually, this is already supported in some way if you register the type explicitly and distinguish using annotations

Documentation

Updated