AddMvc() und Dependency Injection in ASP.NET core

Ich will ehrlich zu euch sein, ich schreibe keine Software Tests. Niemals. Eine Weile habe ich mich mit Angular.js (die erste Version) sehr intensiv auf Pro Level beschäftigt und da kommt man ja irgendwie nicht dran vorbei. JavaScript Code ist einfach die Qualitätshölle, weshalb man wiederum ein Framework wie Jasmin für testen braucht. Als .NET Entwickler findet der Compiler die meisten Fehler, vor allem wenn es um Typ Konflikte geht. Angular ab Version 2 habe ich nach kurzem einarbeiten in die Ecke gestellt. Nun bin ich an ASP.NET core dran und bleibe es auch. Viele Dinge gehen mit Razor und seinen Taghelpern supereinfach. Passt.

ASP.NET Core setzt stark auf seinen Dependency Injection Container. Zu stark für meinen Geschmack und so ist am Ende an vielen Stellen auf den ersten Blick pure Magie drin. Ob schwarz oder weiss liegt dann im Auge des Betrachters.

DI wie die Experten sagen, erzeugt Objekte nicht per New. Ein Container enthält eine Liste aller Objekte mit ein wenig Metadaten über deren Verwendung. Wenn man das Objekt verwenden möchte wird es als Parameter in einen Klassenkonstruktor oder Methode injiziert. Im folgenden C# Code der Startup.cs werden auf verschiedene Arten Klassen der Service Collection hinzugefügt. Ein Service ist eine Klasse samt Initialisierungsanweisung (AddSingleton oder AddTransient) und ggf. Konfiguration.

   1:  public void ConfigureServices(IServiceCollection services)
   2:   {
   3:      services.AddMvc();
   4:      services.AddSignalR();
   5:      services.AddTransient<ppedvService>();
   6:      services.AddSingleton<IConfiguration>(Configuration);

Für mich fängt das Problem schon in Zeile 1 an. Ist das ein normaler Methoden Parameter oder ein DI Objekt. Ich vermute das es ein Parameter ist, der von OWIN gefüllt wird, weil in Methodenparametern das Attribut [FromServices] vor dem Parameter stehen muss/soll/kann. So ein Parameter scheint von DI Container ausgewertet zu werden.

Einfach als Beispiel eines Services. Diese Methode myGetService kann nicht aus normalen Code aufgerufen werden mit MyGetService() weil dann der Parameter fehlt.

   1:  public IServiceCollection myGetServices([FromServices]IServiceCollection services)
   2:          {
   3:              return services;
   4:          }

Die Probleme werden aber in der nächsten Zeile 3 nicht weniger. AddMvc ist eine Extension Methode, die ganze viele AddTransient, AddScoped oder AddSingleton ausführt. Über 200 wenn man dem Debugger glauben schenkt. Und für mich ist der Debugger praktisch Moses samt Steintafeln.

Anmerkung 2019-01-26 161630

Offen bleibt welche Objekte AddMvc nun genau hinzufügt. In einem größeren Context einer Signalr Hub Klasse nutze ich nun drei Objekte ViewEngine, TempData und Service. Da diese Singleton instanziiert wurden vom irgendwem in der OWIN Pipeline. (ja genau ich habe keine Ahnung von wem). Nun sind diese Objekte schon so gefüllt wie man es braucht. Um die über den Zeitraum der Initialisierung zu retten, werden interne Variablen angelegt.

   1:  public SampleHub( IRazorPartialToStringRenderer rdr, IRazorViewEngine viewEngine,
   2:              ITempDataProvider tempDataProvider,
   3:              IServiceProvider serviceProvider)
   4:          {
   5:              renderer = rdr;
   6:              _viewEngine = viewEngine;
   7:              _tempDataProvider = tempDataProvider;
   8:              _serviceProvider = serviceProvider;
   9:          }

Ehrlich, finde ich blöd. Das Zeugs ist irgendwie da und man muss so viel Aufwand treiben um eine Instanz der ViewEngine zu erhalten.

Nun versuche ich auf die anfänglich erwähnte Service Collection von DI Objekten direkt zuzugreifen. Mit der GetService Methode bekommt man eine Instanz des bestimmten Service Typs wie in Startup definiert.

   1:  HttpContext httpCtx = GetHttpContextExtensions.GetHttpContext(this.Context);
   2:  var rndr = httpCtx.RequestServices.GetService<RazorPartialToStringRenderer>(); 

Abhängigkeiten innerhalb der Objekthierarchie werden vom DI Container automatisch (Magie) aufgelöst. Der manuelle Zugriff sollte eigentlich nicht nötig sein.

Eventuell werde ich diesen Blog Artikel überarbeiten, wenn mein (Er) Kenntnisstand wächst.

Kommentare sind geschlossen