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:
GlobalConfiguration.Configuration.DependencyResolver
(gibt Objekte aus dem Root-Bereich zurück) 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.
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.
Tags und Links asp.net-web-api autofac fluentvalidation