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-запросов для каждого запроса - это должно быть полезно.