воскресенье, 2 августа 2015 г.

ASP.NET Core: Dependency Injection

ASP.NET 5 имеет механизм внедрение зависимостей. Этот пост - краткий обзор внедрения зависимостей в ASP.NET 5 с некоторыми примерами.

Регистрация сервисов

Сервисы регистрируются, когда приложение запускается. Это происходит в Startup классе. Этот класс содержит ConfigureServices() метод и в конце этого метода я обычно объявляю маппинг сервисов.


Доступные скоупы:
  • Singleton - всегда возвращать один и тот же экземпляр объекта (сервиса)
  • Transient - каждый раз возвращать новый экземпляр
  • Skoped - возвращать один и тот же экземляр в текущем скоупе (это как singleton в текущем скоупе). Скоупом может быть, например, http-запрос (в течение обработки запроса все потребители будут работать с одним и тем же экземпляром объекта, например, подключением к базе данных DbConnection)
  • Instance - кажый раз возвращается конкретный экземпляр (смотрите выше LocalizationService)
Сервисы, зарегистрированные во время запуска приложения доступны всех классах через внедрение зависимостей.

Также доступны системные переменные и классы. Например, можно внедрить и использовать IApplicationEnvironment.

Давайте посмотрим, как внедрение зависимостей работает с контроллерами и вьюхами. Да-да, с вьюхами тоже! :)

Ранее приходилось создавать фабрику контроллеров для испльзуемого DI контейнера  (Ninject, Castle Windsor, Autofac). Сейчас этого делать не нужно. Но вы по прежнему можете использовать свой любимый DI контейнер и заменить им стандартный. Но не все DI контейнеры могут работат с .NET Core! Например, Autofac может работать только с полной версией .NET.

Внедрение зависимостей в контроллер

Вот пример внедрения пользовательских сервисов и IApplicationEnvironment в контроллер.


Этот код использует внедрение конструктора (constructor injection) для IProductBuilder и IApplicationEnvironment. Это наиболее распространенная практика, она поддерживается всеми,  известными мне, DI контейнерами.

Для внедрения IClientBuilder используется внедрение свойства (property injection). Для этого используется атрибут FromServices. Такая же возможность есть в Ninject, но ее нет в Castle Windsor.

Мы не должны делать ничего особенного, чтобы внедрение зависимостей заработало. Мы должны просто убедиться, что мы регистрируем наши сервисы при запуске приложения.

Внедрение зависимостей в вьюхи

Теперь можно внедрять сервисы в вьюхи. Для этого используется специальный синтаксис @inject.


@ingect указывает движку представлений (Razor), что мы хотим получить экземпляр LocalizationService.

По поводу полезности этой возможности у нас с коллегой возник довольно жаркий спор. Но я считаю, что эта возможность может пригодиться. Можно внедрять хелперы для работы с html, какие-то хитрые кастомные сервисы для локализации (если вдруг локализация через ресурсы по каким-то причинам не подходит).

Заключение

Внедрение зависимостей в ASP.NET 5 очень прозрачное и легко настраивается. Вначале регистрируем маппинг в Startup классе и потом испльзуем внедрение конструктора для получения экземпляров наших классов. В MVC мы можем использовать внедрение зависимостей для контроллеров, вьюх и вью-конпонент (view components, появились в MVC 6, но это уже тема отдельной статьи)