With many dependency injection frameworks, your XML mapping files can quickly grow large and difficult to navigate. With Ninject, your type bindings are collected into groups called modules. Each of these modules represents an independent segment of your application. They can be organized however you like. Modules just need to implement the
IModule interface, but most should extend the StandardModule class for simplicity. Here's an example:
C#:
class WarriorModule : StandardModule {
public override Load() {
Bind<IWeapon>().To<Sword>();
Bind<Samurai>().ToSelf();
}
}
VB.NET:
Public Class WarriorModule
Inherits StandardModule
Public Overrides Sub Load()
Bind(Of IWeapon).To(Of Sword)()
Bind(Of Samurai).ToSelf()
End Sub
End Class
Once you create modules, you load them into a container called the kernel. As the name suggests, the kernel is the core of your application. To request an instance of a type from Ninject, you call the kernel's
Get() method.
This example illustrates how to create a kernel, and activate and use an instance of the
Samurai type:
C#:
class Program {
public static void Main() {
IKernel kernel = new StandardKernel(new WarriorModule());
Samurai warrior = kernel.Get<Samurai>();
warrior.Attack("the evildoers");
}
}
VB.NET:
Module Module1
Sub Main()
Dim kernel As IKernel = New StandardKernel(New WarriorModule())
Dim warrior As Samurai = kernel.Get(Of Samurai)()
warrior.Attack("evil doers")
End Sub
End Module
After Ninject works its magic, the result of the call to
Get() is a
Samurai armed with a
Sword. Therefore, the call to the
Samurai's
Attack() method results in the same output that we saw earlier:
Chopped the evildoers clean in half. More information about the full process Ninject follows when
Get() is called is described in
The Activation Process.
You can create as many modules as you'd like, and pass them all to the kernel's constructor:
C#:
class Module1 {
public void Load() { ... }
}
class Module2 {
public void Load() { ... }
}
class Program {
public static void Main() {
IKernel kernel = new StandardKernel(new Module1(), new Module2(), ...);
...
}
}
VB.NET:
Public Class Module1
Public Sub Load()
...
End Sub
End Class
Public Class Module2
Public Sub Load()
...
End Sub
End Class
Module Program1
Sub Main()
Dim kernel As IKernel = new StandardKernel(New Module1(), New Module2(), ...)
End Sub
End Module
Also, keep in mind that modules are executed just like any other code in your application. Nothing says they're limited to a boring, static collection of bindings. You can always do more creative things like this:
C#:
class WeaponsModule {
private readonly bool _useMeleeWeapons;
public WeaponsModule(bool useMeleeWeapons) {
_useMeleeWeapons = useMeleeWeapons;
}
public void Load() {
if (useMeleeWeapons)
Bind<IWeapon>().To<Sword>();
else
Bind<IWeapon>().To<Shuriken>();
}
}
class Program {
public static void Main() {
bool useMeleeWeapons = false;
IKernel kernel = new StandardKernel(new WeaponsModule(useMeleeWeapons));
Samurai warrior = kernel.Get<Samurai>();
warrior.Attack("the evildoers");
}
}
VB.NET:
Public Class WeaponsModule
Inherits StandardModule
Private ReadOnly _useMeleeWeapons As Boolean
Public Sub New(ByVal useMeleeWeapons As Boolean)
_useMeleeWeapons = useMeleeWeapons
End Sub
Public Overrides Sub Load()
If (_useMeleeWeapons) Then
Bind(Of IWeapon).To(Of Sword)()
Else
Bind(Of IWeapon).To(Of Sword)()
End If
End Sub
End Class
Module Module2
Dim useMeleeWeapons As Boolean = False
Dim kernel As IKernel = New StandardKernel(New WeaponsModule(useMeleeWeapons))
Dim warrior As Samurai = kernel.Get(Of Samurai)()
warrior.Attack("the evildoers")
End Module
This will result in our
Samurai being armed with a
Shuriken, causing the output
Pierced the evildoers armor. If you set the
useMeleeWeapons flag to true, the binding would be from
IWeapon to
Sword, resulting in the output
Chopped the evildoers clean in half. Many more advanced scenarios are possible, including reading configuration files, command-line arguments, and the like. And we still haven't even talked about contextual bindings! :)
Continue reading:
Providers and the Activation Context