Dependency Injection mit Ninject und ASP.NET MVC 3

In den letzten Tagen habe ich mich mal etwas näher mit der neuen Auskopplung des MVC Frameworks (ASP.NET MVC 3) beschäftigt. Nicht nur die Viewengine Razor ist hinzugefkommen, es hat sich auch einiges unter der Haube getan. Mich interessiert aktuell die vereinfachte Einbindung von Dependency Injection (IoC). Als DI-Container verwende ich Ninject und bin bisher auch sehr zufrieden damit.

In MVC3 kann man den DI-Container über die vorhandene Klasse DependencyResolver registrieren lassen. Dazu ruft man die Methode SetResolver auf und übergibt ein von IDependencyResolver abgeleitetes Objekt. Natürlich muss man das nicht selbst schreiben. Auch hier hat Ninject etwas zu bieten. Sucht in NuGet nach Ninject.MVC3. Die Assembly enthält nur eine Klasse namens NinjectServiceLocator und hierin eine Methode GetService(Type).

Um Ninject nun zu verwenden, benötigt man wie bisher auch einen Kernel. (Informationen zu Ninject gibt es auch auf Codeplex.) Dazu habe ich mal eine einfache Factory geschrieben, die nach belieben noch erweitert werden kann.

[csharp]
namespace Mvc3App.Infrastructure
{
public static class KernelFactory
{
public static IKernel GetKernel()
{
bool isStaging = bool.Parse(ConfigurationManager.AppSettings[„staging“]);
NinjectModule module = isStaging ? new TestModule() as NinjectModule : new ProductionModule() as NinjectModule;
return new StandardKernel(module);
}
}
}
[/csharp]

In der global.asax.cs muss man nun den Container (Kernel) in der MVC Pipeline registrieren. Hier kommt auch gleich die zusätzliche Assembly zum Einsatz. Ab Version 3 reicht es aus, den Resolver der MVC Engine zu übergeben.

[csharp]
protected void Application_Start()
{
AreaRegistration.RegisterAllAreas();

RegisterGlobalFilters(GlobalFilters.Filters);
RegisterRoutes(RouteTable.Routes);

//initialize DI-Container
Ninject.Mvc3.NinjectServiceLocator sl = new NinjectServiceLocator(Infrastructure.KernelFactory.GetKernel());
DependencyResolver.SetResolver(sl);
}
[/csharp]

Das war es eigentlich auch schon mit dem ganzen Hexenwerk. Alles andere funktioniert wie bisher auch. Man muss Module anlegen, in denen das Binden der Typen erfolgt. Wie in der Kernelfactory zu erkennen ist, habe ich mal zwei Module, eines für die Testumgebung und eines für die Produktivumgebung, erstellt.

[csharp]
namespace Mvc3App.Infrastructure
{
public class TestModule : NinjectModule
{
public override void Load()
{
Bind().To();
}
}

public class ProductionModule : NinjectModule
{
public override void Load()
{
Bind().To();
}
}
}
[/csharp]

Die Schnittstelle des Repositories und deren Implementierungen schenke ich mir jetzt mal. Diese kann ich aber auf Wunsch auch zur Verfügung stellen. Da es aber sowieso nur eine Methode „GetPersons(int)“ gibt, muss das nicht sein.

Im Controllerbereich habe ich einen Basiscontroller angelegt. Der bekommt in eine Property den Kernel injiziert. Dieser wird benötigt, wenn man im Code einen Typ erzeugen möchte. Da diese Art der Entwicklung aber nicht notwendig ist, gehe ich hierauf auch nicht weiter ein. Zum Andeuten des einfachen Verwendung, habe ich im Homecontroller einen Konstruktor aufgenommen, der ein IPersonRepositorty verlangt. Das Objekt wird von Ninject erzeugt und zur Verfügung gestellt und dem Konstruktor injiziert.

[csharp]
namespace Mvc3App.Controllers
{
public class BaseController : Controller
{
[Inject]
public IKernel Kernel { get; set; }

}

public class HomeController : BaseController
{
private IPersonRepository repos;

// Respitory wird ‚injiziert‘ (constructor injection)
public HomeController(IPersonRepository repos)
{
this.repos = repos;
}
}
}
[/csharp]

Über den Verwendung von DI-Container und die Herangehensweise bei der Programmierung geben die im Text enthaltenen Links schon eine gute Auskunft. Ich wollte hier keine Einführung in das Thema geben, sondern nur auf die Neuerungen im Zusammenhang mit ASP.NET MVC3 hinweisen. Um ein kurzes Beispiel Praxisbeispiel kommt man aber nicht drumherum.

Kommentar verfassen

Trage deine Daten unten ein oder klicke ein Icon um dich einzuloggen:

WordPress.com-Logo

Du kommentierst mit Deinem WordPress.com-Konto. Abmelden /  Ändern )

Google Foto

Du kommentierst mit Deinem Google-Konto. Abmelden /  Ändern )

Twitter-Bild

Du kommentierst mit Deinem Twitter-Konto. Abmelden /  Ändern )

Facebook-Foto

Du kommentierst mit Deinem Facebook-Konto. Abmelden /  Ändern )

Verbinde mit %s