DivineInject is a .net dependency injection framework, designed to be simple to use and easy to understand.
You can find the source for DivineInject on github.
Why another DI framework?
Because dependency injection is important – but done wrong it can do more harm than good. DivineInject is opinionated about the right way to use dependency injection:
- Constructor injection or death
Setter injection is bad for your health, so just say no
- Dependencies are singletons
Dependencies are external to your application – your DI framework doesn’t need to know about users or sessions or threads.
- Domain objects can be rich, too
Your domain model doesn’t have to be anemic
Setter and method injection are much harder to get right – so DivineInject simply doesn’t support them. If you can’t implement your dependencies as constructor arguments, then maybe you should refactor the dependency so you can.
Dependencies are external to your application. They are external things that your application depends on like databases and web services; these things are generally used across your application. Hint: if a dependency is only used in one or two places, it isn’t an application-wide dependency.
Things like users and sessions are domain concepts in your domain, not in the domain of dependency injectors. All dependency injection frameworks get wrapped up in different scopes, which makes the frameworks harder to use. DivineInject simply doesn’t support them — if you need something user-scoped or session-scoped, then implement the logic yourself. It isn’t hard, and if you ever want to understand the lifecycle of your objects it’s in your code, not mine — which will make reasoning about your code or debugging it a million times easier.
Rich Domain Objects
DivineInject borrows an idea from Google Guice – with Guice it is called “assisted injection”, in DivineInject we call it generated factory injection. The idea is the same — providing a simple way to create objects with constructors which accept runtime arguments as well as dependencies to inject. This allows you to create rich, stateful domain objects which also have dependencies.
So how do you get started with DivineInject? I’ll assume you’ve not been living under a rock and already know what dependency injection is. In which case basic usage of DivineInject boils down to three steps:
- Add the dependency
- Configure bindings
- Create your root object
Add the Dependency
DivineInject is available as a NuGet package:
When DivineInject creates a new instance of a class it calls a constructor, each of the constructor arguments is a dependency of the class — something external to the class, for which an implementation must be provided. But how do we know which value to pass for each dependency? This is controlled by the bindings.
Your bindings must be configured near the start of your application — e.g. in the main method or global.asax.
There are basically two ways to configure bindings with DivineInject.
1) bind an interface to a concrete type. DivineInject will pass the same (singleton) instance of the given concrete type whenever it encounters a constructor argument of the interface type.
2) bind an interface to a specific instance. DivineInject will pass the given instance whenever it encounters a constructor argument of the interface type.
var myOrdersService = new OrdersService(...);
Create Your Root Object
DivineInject allows you to create a tree of objects — each object has references to dependencies, which in turn reference their own dependencies; forming a tree of objects. This tree is created starting with the root object — e.g. in a WPF application the root would be the outermost ViewModel; in a WCF application it would be the service class.
The root object is created by calling DivineInject — any arguments the root object constructor requires are taken from the bindings. This should be the only time you explicitly call DivineInject to create objects.
There are two ways of creating the root object:
1) by explicit type:
private MainWindowViewModel CreateViewModel()
2) by passing the type as an argument:
public object GetInstance(InstanceContext instanceContext,
At this point you now have a very simple set of dependencies configured, which can be wired up by DivineInject. E.g.
public class MainWindowViewModel
public MainWindowViewModel(IOrdersService ordersService)
I can define classes which accept an instance of an interface as a constructor argument, when DivineInject instantiates this class it will pass in the right implementation of the interface, the one configured by the bindings.
In the second part of this series, we’ll look at how we use DivineInject to create classes that aren’t singletons.