2013-02-22 10 views
8

W MVC, instancja ModelValidatorProvider jest wywoływana i wywoływana w celu sprawdzenia poprawności modelu dla każdego żądania. Oznacza to, że w środowisku DI może on pobierać zależności od obiektów o zakresie określonym w pojedynczym żądaniu, na przykład w kontekście jednostki pracy lub bazy danych. W Web API wygląda na to, że zmieniło się znacząco. Zamiast tworzenia instancji na żądanie, ModelValidatorProvider wydaje się być długowieczne i tworzone w ramach uruchamiania aplikacji. WebAPI następnie buforuje wyniki z typu ModelValidatorProvider, co oznacza, że ​​ModelValidator nie może pobierać żadnych zależności od DI.Per-Request DependencyResolver w Web API

Próbuję wdrożyć mój ModelValidator, aby użyć fabryki za pomocą Lokalizatora usług (proszę, nie ma automatycznych komentarzy "anty-wzór"!). Umożliwiłoby to skonstruowanie wewnętrznego obiektu walidatora w ramach każdego żądania, który byłby w stanie pobrać zależności z kontenera. Nie mogę jednak uzyskać rozstrzygnięcia zależności lub zakresu kontenera na bieżące żądanie od tego ModelValidator, które ma zasięg w zasadzie jako Singleton. Próbowałem użyć GlobalConfiguration.Configuration.DependencyResolver, ale to tylko wraca globalnie scoped usług (z zakresu korzeni, również mentioned here)

pracuję w Autofac, więc rozwiązanie autofac specyficzne byłby odpowiedni (np MVC ma AutofacDependencyResolver.Current , który używa wewnętrznie DependencyResolver.GetService). W integracji WebAPI nie ma odpowiednika, prawdopodobnie z powodu wyżej wspomnianego powodu, w którym globalny DependencyResolver zwraca tylko usługi o zasięgu globalnym.

Powodem, dla którego próbuję to zrobić (jak również na własny użytek) jest wdrożenie integracji Web API dla FluentValidation, która obecnie nie istnieje. Do tej pory były dwie próby, ale żadna z nich nie rozwiązuje problemu Dependency Injection, a zamiast tego powoduje pojedynczą statyczną metodę ModelValidator.

Czego próbowałem dotąd:

  • Korzystanie GlobalConfiguration.Configuration.DependencyResolver (zwraca obiekty z zakresu korzenia)
  • podjęciem zależność od Func<IComponentContext> (zawsze zwraca kontekst root)

W odpowiedź, która od tego czasu została usunięta, zaproponowano usunięcie usługi z konfiguracji Web API. Musiało to zostać wykonane za pomocą refleksji, ponieważ interfejs i klasy implementacji są zdefiniowane jako wewnętrzne, ale sprawiły, że walidatory działają lepiej (ponieważ ModelValidator został skonstruowany na żądanie). Istnieje jednak znaczący hit wydajnościowy, aby zrobić to w ten sposób z powodu użycia refleksji do sprawdzenia walidatorów w modelu i każdej posiadanej nieruchomości, więc nie chcę tej opcji.

Odpowiedź Filipa sugeruje użycie HttpRequestMessage w celu uzyskania zasięgu zależności, ale nie znalazłem niczego takiego jak HttpRequestMessage.Current, który zapewniłby dostęp do tego obiektu z obiektu długożyciowego - jeśli to można osiągnąć, wierzę, że wszystko układać się.

Odpowiedz

3

Aby uzyskać aktualny zakres zależność, trzeba użyć (niespodzianka :) GetDependencyScope() bieżącego HttpRequestMessage (o którym można przeczytać on MSDN) zamiast GlobalConfiguration.

Jakiś czas temu blogowałem o numerze Web API per-request dependency scope - powinno to być pomocne.

+6

Wygląda na to, że może być bliżej rozwiązania, ale jak mogę uzyskać HttpRequestMessage? To jest z długo trwającej klasy. Googling sugeruje, że nie jest to możliwe. – Richard