DependencyResolver по запросу в веб-API

В MVC, ModelValidatorProvider создается и вызывается для проверки модели по каждому запросу. Это означает, что в среде DI он может зависеть от объектов, находящихся в пределах одного запроса, например, от единицы работы или контекста базы данных. В веб-API это, по-видимому, значительно изменилось. Вместо того, чтобы создаваться для каждого запроса, ModelValidatorProvider кажется долгоживущим и создается в момент запуска приложения. Затем Web API кэширует результаты из ModelValidatorProvider для каждого типа, что означает, что ModelValidator не может принимать какие-либо зависимости от DI.

Я пытаюсь реализовать свой ModelValidator использовать фабрику с помощью сервисного локатора (пожалуйста, не используйте автоматические комментарии против шаблонов!). Это позволило бы мне создать внутренний объект валидатора в каждом запросе, который мог бы принимать зависимости от контейнера. Тем не менее, я не могу достать Dependency Resolver или контейнер, ограниченный текущим запросом изнутри этого ModelValidator который по сути ограничен как синглтон. Я пытался использовать GlobalConfiguration.Configuration.DependencyResolver, но это возвращает только глобально доступные сервисы (из корневой области, также упомянутой здесь)

Я работаю в Autofac, поэтому было бы целесообразно использовать конкретное решение (например, MVC имеет AutofacDependencyResolver.Current, который внутренне использует DependencyResolver.GetService). В интеграции Web API нет эквивалента, вероятно, по причине, упомянутой выше, где глобальная DependencyResolver возвращает только глобальные сервисы.

Причина, по которой я пытаюсь сделать это (а также для собственного использования), заключается в реализации интеграции Web API для FluentValidation, которой в настоящее время не существует. До сих пор было две попытки, но ни одна из них не решает проблему внедрения зависимостей и вместо этого приводит к единственному статическому ModelValidator.

Вещи, которые я пробовал до сих пор:

  • С помощью GlobalConfiguration.Configuration.DependencyResolver (возвращает объекты из корневой области видимости)
  • Принимая зависимость от Func<IComponentContext> (всегда возвращает корневой контекст)

В ответе, который с тех пор был удален, было предложено удалить IModelValidatorProvider сервис из конфига Web API. Это должно было быть сделано с использованием отражения, поскольку интерфейс и реализующие классы все определены как внутренние, но это действительно помогло валидаторам работать лучше (потому что ModelValidator был создан для каждого запроса). Тем не менее, это значительно ухудшает производительность из-за использования отражения для проверки валидаторов в модели и всех ее свойств, поэтому я не хочу использовать эту опцию.

Ответ Филипа В. предлагает использовать HttpRequestMessage для получения области зависимостей, но я не нашел ничего такого, как HttpRequestMessage.Current который обеспечил бы доступ к этому объекту из долгоживущего объекта - если бы это могло быть достигнуто, я верю, что все встало бы на свои места.

1 ответ

Чтобы получить текущую область зависимостей, вы должны использовать (сюрприз, сюрприз:) GetDependencyScope() текущего HttpRequestMessage (подробнее о котором вы можете прочитать в MSDN) вместо GlobalConfiguration,

Некоторое время назад я писал в блоге об области зависимости Web-запросов для каждого запроса - это должно быть полезно.

Другие вопросы по тегам