ASP.NET MVC 6 Dependency Injection (внедрение зависимости)

Ниже будет слегка рассмотрена реализация dependency injection от ms в рамках базового шаблона ASP.NET MVC 6
Использованные классы написаны только для демонстрации и некоторые вещи не стоит делать в проде
Также для всего этого дела использованы некоторые фичи C# 6, just for fun
Извлечение реализации определённого интерфейса будет представлено в четырёх видах (хотя все они сводятся к одному, но при использовании сильно отличаются)

Итак, подробный разбор ниже
Всё относительно просто:
  1. Качаем Visual Studio 2015 RC (я использовал Community Edition)
  2. Создаём проект
    1.  
    2. Проверяем, что  проект компилируется и запускается
    3. Далее (CTRL+\, CTRL+M) (переход в TeamExplorer)
    4. Делаем первый комит
        
  3. В целом всё готово, не буду создавать лишние проекты или папки, просто всё новое будем складывать в новый каталог Lib в корне проекта
  4. Для начала создадим классы, генерирующие данные и разместим их в файле /Lib/Faker.cs (я не стал их сам писать, просто нашёл на кодплексе)


  5. Далее создаём какой-нибудь класс данных, допустим SomeClass

  6. Теперь создадим интерфейс и его реализацию, собственно их и будем регистрировать в DI от MS


  7. И так, всё готово, получилась следующая структура:
    1. Переходим в файл Startup.cs (класс startup)
    2. находим метод ConfigureServices
    3. В самом конце рагистрируем реализацию интерфейса:
      services.AddTransient<ISomeProvider, SomeProvider>();


    Пробуем использовать

    Для начала запустим проект и убедимся, что всё работает:

    Для простоты фейковые данные буду выводить на главной странице, предположим, что это список последних отзывов о продукте

    Для этого заходим во вьюху /Views/Home/Index.cshtml
    Определяем тип модели как TestDependencyInjection.Lib.SomeClass через дерективу @model:
    @model IEnumerable<TestDependencyInjection.Lib.SomeClass>

    А в самый конец добавляем вывод данных модели:

    Ввиду того, что дефолтный шаблон использует bootstrap, то его стили и были заюзаны, не без помощи сайта http://getbootstrap.com/components/

    Теперь нужно передавать данные во вьюху, передаваться они будут одним способом, а вот получение реализации интерфейса рассмотрим несколько

    Способ первый

    1. Открываем контроллер HomeController
    2. Находим метод Index()
    3. Меняем на следующее:

    4. Запускаем, профит:


    Способ второй

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

    Конечно можно определить поле, и в конструкторе его уже инициализировать, но часть работы, для этого случая, на себя берёт .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

    Плюс все описанные шаги можно наблюдать в гите после открытия проекта:

      Комментариев нет:

      Отправить комментарий

      Можете оставить свой комментарий