DependencyResolver pro Anfrage in der Web-API

8

In MVC wird ein ModelValidatorProvider instanziiert und aufgerufen, um ein Modell bei jeder Anfrage zu validieren. Dies bedeutet, dass es in einer DI-Umgebung Abhängigkeiten von Objekten annehmen kann, die innerhalb einer einzelnen Anforderung, z. B. einem Arbeitseinheits- oder Datenbankkontext, definiert sind. In der Web-API scheint dies erheblich geändert worden zu sein. Anstatt pro Anfrage instanziiert zu werden, scheint ModelValidatorProvider langlebig zu sein und innerhalb des Anwendungsstarts instanziiert zu werden. Die WebAPI speichert dann die Ergebnisse vom ModelValidatorProvider per-Typ, was bedeutet, dass ModelValidator keine Abhängigkeiten von DI annehmen kann.

Ich versuche mein ModelValidator zu implementieren, um eine Fabrik zu verwenden, die einen Service Locator benutzt (bitte, keine automatischen "Anti-Muster" Kommentare!). Dies würde es mir ermöglichen, innerhalb jeder Anfrage ein internes Validator-Objekt zu konstruieren, das Abhängigkeiten vom Container übernehmen könnte. Ich kann jedoch keinen Dependency Resolver oder Container erreichen, der auf die aktuelle Anforderung innerhalb dieses ModelValidator beschränkt ist, das im Wesentlichen als Singleton definiert ist. Ich habe versucht, GlobalConfiguration.Configuration.DependencyResolver zu verwenden, aber dies gibt nur Dienste mit globalem Umfang zurück (aus dem Stammbereich, auch hier erwähnt )

Ich arbeite in Autofac, daher wäre eine Autofac-spezifische Lösung geeignet (z. B. MVC hat AutofacDependencyResolver.Current , die intern DependencyResolver.GetService verwendet). Es gibt kein Äquivalent in der WebAPI-Integration, vermutlich aus dem oben genannten Grund, wo das globale DependencyResolver nur global-scoped Dienste zurückgibt.

Der Grund, warum ich dies (und auch für mich selbst) versuche, ist die Implementierung der Web-API-Integration für FluentValidation, die es derzeit nicht gibt. Bisher gab es zwei Versuche, aber keiner von ihnen behandelt das Dependency Injection-Problem und stattdessen einen einzelnen statischen ModelValidator.

Dinge, die ich bisher versucht habe:

  • Verwendung von GlobalConfiguration.Configuration.DependencyResolver (gibt Objekte aus dem Root-Bereich zurück)
  • Abhängigkeit von Func<IComponentContext> (gibt immer den Wurzelkontext zurück)

In einer Antwort, die seitdem entfernt wurde, wurde vorgeschlagen, IModelValidatorProvider service aus der Web-API-Konfiguration zu entfernen. Dies musste mit Reflektion geschehen, da die Schnittstelle und die implementierenden Klassen alle als intern definiert sind, aber die Validatoren funktionierten besser (weil der ModelValidator pro Anfrage erstellt wurde). Es gibt jedoch eine erhebliche Leistungseinbuße, dies zu tun, da Reflektion verwendet wird, um nach Validatoren auf dem Modell und jeder Eigenschaft zu suchen, die es hat, also möchte ich diese Option nicht verwenden.

Die Antwort von Filip W schlägt vor, HttpRequestMessage zu verwenden, um den Abhängigkeitsbereich zu erhalten, aber ich habe nichts wie HttpRequestMessage.Current gefunden, das Zugriff auf dieses Objekt innerhalb eines langlebigen Objekts bietet - wenn das möglich ist, glaube ich alles würde sich einfügen.

    
Richard 22.02.2013, 14:25
quelle

1 Antwort

3

Um den aktuellen Abhängigkeitsbereich zu erhalten, müssen Sie (Überraschung, Überraschung :) GetDependencyScope() des aktuellen HttpRequestMessage verwenden (mehr darüber können Sie auf MSDN ) anstelle von GlobalConfiguration .

Ich habe über Web-API pro Anfrage gebloggt Abhängigkeitsbereich vor einiger Zeit - das sollte hilfreich sein.

    
Filip W 22.02.2013 14:59
quelle