Внедрение зависимости (dependency injection) в контроллерах ASP.NET MVC

| Четверг, 28 марта, 2013

Метки: ASP.NET MVC Комментарии: 1

Контроллеры в ASP.NET MVC принимают и обрабатывают входящие HTTP-запросы, они принимают данные от клиента, а также отсылают ответ обратно клиенту. Контроллеры действуют как координаторы между моделями и представлениями. Среда ASP.NET MVC сама создает объекты контроллеров во время выполнения. Для этого требуется только одно условие – конструктор должен быть без параметров. Но как передавать объекты в контроллеры? Если просто передать параметры в конструктор контроллера, то среда выполнения выдаст ошибку при попытке создать контроллер. В этом случае контроллер нужно создавать самому и внедрять зависимости.

Существует много способов внедрения зависимости в класс. Например, можно установить свойство, передать через метод или внедрить через конструктор. Рассмотрим, способ внедрения зависимости через конструктор контроллера. Без создания фабрики контроллеров нельзя внедрить зависимости в контроллеры. Поэтому рассмотрим еще создание простейшей фабрики контроллеров и зарегистрируем ее в ASP.NET MVC.

Зачем нужно внедрять зависимости в контроллер?

Почти во всех реальных приложениях ASP.NET MVC требуется внедрять зависимые компоненты. Можно, конечно, создать компонент прямо внутри контроллера, но тогда контроллер будет сильно связан с этим компонентом. Если у компонента изменится реализация или выйдет новая версия, то придется изменять код внутри контроллера. Другая проблема возникнет, когда нужно будет написать автоматизированные тесты для контроллера. Тесты со stub-изоляцией и моками реализовать не получится.

Структура контроллера

Структура контроллера ASP.NET MVC определена абстрактным классом Controller. Каждый контроллер, создаваемый в приложении ASP.NET MVC, должен наследоваться от этого класса. Ниже показана иерархия наследования.

Корневой элемент – интерфейс IController. Его абстрактная реализация класс ControllerBase. Далее от ControllerBase наследуется абстрактный класс Controller, от которого наследуются все пользовательские контроллеры приложения.

Простые пользовательские контроллеры

При создании проекта ASP.NET MVC 4 через шаблон Internet Application, автоматически генерируются два контроллера – AccountController и HomeController.

При исследовании кода HomeController можно заметить, что класс контроллера не имеет конструктора.

public class HomeController : Controller
{
    public ActionResult Index()
    {
        ViewBag.Message = "Modify this template to jump-start your ASP.NET MVC application.";
        return View();
    }
    public ActionResult About()
    {
        ViewBag.Message = "Your app description page.";
        return View();
    }
} 

Если конструктор не определен, то .NET Framework во время компиляции создаст конструктор без параметров.

public class HomeController : Controller
{
    public HomeController()
    {
    }
} 

Создадим интерфейс ILogger и его реализацию класс DefaultLogger.

public interface ILogger
{
    void Log(string logData);
}
public class DefaultLogger : ILogger
{
    public void Log(string logData)
    {
        System.Diagnostics.Debug.WriteLine(logData, "default");
    }
} 

Внедрим интерфейс через конструктор класса.

public class HomeController : Controller
{
    private readonly ILogger _logger;
    public HomeController(ILogger logger)
    {
        _logger = logger;
    }
} 

Класс DefaultLogger пока нигде не создается. Так как, класс контроллера создается внутри фреймворка ASP.NET MVC, то непонятно, где создать объект DefaultLogger и как его передать через конструктор внутрь контроллера. При построении проекта ошибок не появляется, но во время выполнения генерируется исключение : "Для объекта не определен конструктор без параметров".

Класс DefaultControllerActivator сгенерировал ошибку MissingMethodException. Это значит, что среда ASP.NET MVC пытается вызвать конструктор без параметров и не может создать объект контроллера. Но как же передать тогда объект DefaultLogger? Рассмотрим это дальше.

Комментарии
Дмитрий
Фабрика которая выплевывает всегда HomeController?
4 года назад
Войдите, чтобы написать комментарий , или воспользуйтесь формой ниже.
 

Copyright © CodeHint.ru 2013-2024 (v2.4.7 - работает на Angular Universal)Калькулятор инвест-портфеля