-
Notifications
You must be signed in to change notification settings - Fork 7
Injection Patterns
Ninject supports four patterns for injection, which are listed here. All injections are controlled by the [Inject]
attribute. Each kind of injection has its own benefits and detriments, and you may find each to be useful in different circumstances.
The first (and arguably best) type is constructor injection. When activating an instance of a type, if the type has a constructor with an [Inject]
attribute, Ninject will try to activate an object for each of the constructor’s parameters.
class Samurai {
private readonly IWeapon _weapon;
[Inject]
public Samurai(IWeapon weapon) {
_weapon = weapon;
}
public void Attack(string target) {
_weapon.Hit(target);
}
}
When in doubt, use constructor injection, because it lets you inject multiple dependencies at once, and add the readonly
keyword to the fields that hold the injected values. (Using readonly
is a matter of taste, and is entirely up to you. Ninject doesn’t mind either way.)
An important note! You can only have one constructor of your type marked with an [Inject]
attribute. If you put an [Inject]
attribute on more than one constructor, Ninject will throw a NotSupportedException
the first time an instance of the type is requested.
You also have the option to leave off the [Inject]
attribute completely. This can help if you don’t have access to the source code of a class, but you still want to inject dependencies into it. Here’s the logic Ninject follows to choose which constructor to call, if none have an [Inject]
attribute:
- If the type only has a single constructor, Ninject will call it.
- If the type has more than one constructor, but has a default (parameterless) constructor available, Ninject will call it. (This also applies to types that have no explicit constructors defined.)
Here’s an example of our same Samurai
class using property injection. Unlike constructor injection, you can have multiple properties decorated with an [Inject]
attribute.
Be careful! The order of property injection is not deterministic, meaning there is no way to tell in which order Ninject will inject their values in. (However, you can also request notification when all injections are complete by implementing either the the IInitializable
or the IStartable
interface, discussed later.)
class Samurai {
private IWeapon _weapon;
[Inject]
public IWeapon Weapon {
get { return _weapon; }
set { _weapon = value; }
}
public void Attack(string target) {
_weapon.Hit(target);
}
}
Here’s method injection. As with constructor injection, you can also inject multiple values at once via the same method. You can also have multiple methods decorated with the [Inject]
attribute. They will all be called, but as with property injection, there is no guarantee on which order they will receive their injections.
class Samurai {
private IWeapon _weapon;
[Inject]
public void Arm(IWeapon weapon) {
_weapon = weapon;
}
public void Attack(string target) {
_weapon.Hit(target);
}
}
And finally, here’s field injection. Same rules apply: multiple fields can have [Inject]
attributes, but the order of their injections is not deterministic.
class Samurai {
[Inject] private IWeapon _weapon;
public void Attack(string target) {
_weapon.Hit(target);
}
}
Although its simplicity is tempting, you should generally try to avoid using field injection, since the value can then only be set via Ninject. This makes unit testing much more complex, since sometimes it’s easiest to use dependency injection by hand to inject mock objects into your unit tests.
Continue reading: Activation Behaviors