Ниже будет слегка рассмотрена реализация dependency injection от ms в рамках базового шаблона ASP.NET MVC 6
Использованные классы написаны только для демонстрации и некоторые вещи не стоит делать в проде
Также для всего этого дела использованы некоторые фичи C# 6, just for fun
Извлечение реализации определённого интерфейса будет представлено в четырёх видах (хотя все они сводятся к одному, но при использовании сильно отличаются)
Итак, подробный разбор ниже
Всё относительно просто:
Конечно можно определить поле, и в конструкторе его уже инициализировать, но часть работы, для этого случая, на себя берёт .NET, а именно - передача реализации интерфейса через параметры конструктора контроллера:
Использованные классы написаны только для демонстрации и некоторые вещи не стоит делать в проде
Также для всего этого дела использованы некоторые фичи C# 6, just for fun
Извлечение реализации определённого интерфейса будет представлено в четырёх видах (хотя все они сводятся к одному, но при использовании сильно отличаются)
Итак, подробный разбор ниже
Всё относительно просто:
- Качаем Visual Studio 2015 RC (я использовал Community Edition)
- Создаём проект
-
- Проверяем, что проект компилируется и запускается
- Далее (CTRL+\, CTRL+M) (переход в TeamExplorer)
- Делаем первый комит
- В целом всё готово, не буду создавать лишние проекты или папки, просто всё новое будем складывать в новый каталог Lib в корне проекта
- Для начала создадим классы, генерирующие данные и разместим их в файле /Lib/Faker.cs (я не стал их сам писать, просто нашёл на кодплексе)
- Далее создаём какой-нибудь класс данных, допустим SomeClass
- Теперь создадим интерфейс и его реализацию, собственно их и будем регистрировать в DI от MS
- И так, всё готово, получилась следующая структура:
- Переходим в файл Startup.cs (класс startup)
- находим метод ConfigureServices
- В самом конце рагистрируем реализацию интерфейса:
services.AddTransient<ISomeProvider, SomeProvider>();
Пробуем использовать
Для начала запустим проект и убедимся, что всё работает:
Для простоты фейковые данные буду выводить на главной странице, предположим, что это список последних отзывов о продукте
Для этого заходим во вьюху /Views/Home/Index.cshtml
Определяем тип модели как TestDependencyInjection.Lib.SomeClass через дерективу @model:
@model IEnumerable<TestDependencyInjection.Lib.SomeClass>
А в самый конец добавляем вывод данных модели:
Ввиду того, что дефолтный шаблон использует bootstrap, то его стили и были заюзаны, не без помощи сайта http://getbootstrap.com/components/
Теперь нужно передавать данные во вьюху, передаваться они будут одним способом, а вот получение реализации интерфейса рассмотрим несколько
Теперь нужно передавать данные во вьюху, передаваться они будут одним способом, а вот получение реализации интерфейса рассмотрим несколько
Способ первый
Способ второй
Первый способ понятен, но не шибко удобен, в отношении того, что нужно в каждом классе, а может кто-то захочет и в каждом методе, прописывать такую длинную строчку
Конечно можно определить поле, и в конструкторе его уже инициализировать, но часть работы, для этого случая, на себя берёт .NET, а именно - передача реализации интерфейса через параметры конструктора контроллера:
Способ 2.5
Использование разрешения зависимости через конструктор базового класса
Способ третий
Разрешение зависимости через параметры действия
А именно - если Action необходим для обработки запроса какой-то интерфейс, то пусть Action его и запрашивает в своей сигнатуре, а контроллер может содержать обработчики, которым не нужны вообще никакие заресолвленные через DI классы
Если все такие зависимости запрашивать через конструктор, то может найтись контроллер-монстр, конструктор которого будет требовать IRepository, ISmsProvider, IEmailProvider, ILogHelper, IUserManager и т.п.
Так что попробуем заюзать ModelBinders (с которыми познакомился еще в MVC3)
Для этого создаём новый класс:
Далее идём в класс Startup, в методе ConfigureServices меняем строчку services.AddMvc() на следующие:
Возвращаемся к методу Index контроллера Home и определяем у него ещё один аргумент:
На мой взгляд это самый удобный способ, как в отношении использования DI в контроллерах, так и при написании тестов
А результат тот же:
Кстати, описанный метод действителен и для web api (проверял на второй версии)
Если что-то у самих не получилось, то можете поиграть с собранным и рабочим на момент сборки проектом по ссылке: https://goo.gl/1XyUOo
Плюс все описанные шаги можно наблюдать в гите после открытия проекта:
Возвращаемся к методу Index контроллера Home и определяем у него ещё один аргумент:
На мой взгляд это самый удобный способ, как в отношении использования DI в контроллерах, так и при написании тестов
А результат тот же:
Кстати, описанный метод действителен и для web api (проверял на второй версии)
Если что-то у самих не получилось, то можете поиграть с собранным и рабочим на момент сборки проектом по ссылке: https://goo.gl/1XyUOo
Плюс все описанные шаги можно наблюдать в гите после открытия проекта:
Комментариев нет:
Отправить комментарий
Можете оставить свой комментарий