Pull to refresh

Ставим точки в MVC Framework. Фабрика контроллеров

Reading time 5 min
Views 8.7K
В этой главе ставится точка в ответе на вопрос “Как и зачем работает фабрика контроллеров?”.

imageЭто третья статья из цикла статей про внутреннее устройство MVC Framework. Краткое содержание предыдущих частей: Нужно ли переходить на MVC Framework?; механизм работы MVC Framework: Часть 1 и часть 2. В этой статье речь пойдет о механизме фабрики контроллеров, важной части MVC Framework, с которой начинается работа всего фреймворка.

Почему “фабрика”?


Фабрика – это название паттерна проектирования, который определяет механизм создания объектов (экземпляров классов) без указания самих классов. Подробнее смотрите в wiki. В MVC Framework фабрика контроллеров, как понятно из названия, предназначена для создания объектов контроллеров. Так как информация о требуемом контроллере поступает из механизма маршрутизации ASP.NET в виде строки с именем класса, фабрика контроллеров строит объекты контроллеров на основании этой строки.

Фабрика контроллеров


Обычно, фабрика создает объекты классов, определенного интерфейса. Для фабрики контроллеров MVC Framework таким интерфейсом является IController. В целом определение интерфейса фабрики контроллера выглядит так:
public interface IControllerFactory {
  IController CreateController(RequestContext requestContext, string controllerName);
  void ReleaseController(IController controller);
}


* This source code was highlighted with Source Code Highlighter.

Весьма простой интерфейс: метод CreateController должен возвращать объекты реализующие IController, ReleaseController должен озаботиться удалением контроллера, когда контроллер прекращает свое существование.

Для того, чтобы фабрика контроллеров могла вернуть необходимый экземпляр контроллера, ей передаются параметры в виде имени требуемого контроллера controllerName и контекста запроса requestContext, который формирует механизм маршрутизации ASP.NET. Разработчику ASP.NET MVC Framework нет нужды писать свою реализацию фабрики контроллеров, поскольку фреймворк содержит реализацию фабрики по умолчанию. Этой реализацией является класс DefaultControllerFactory.

DefaultControllerFactory


Когда механизм ASP.NET MVC Framework получает пользовательский запрос, сопоставленный обработчик MvcRouteHandler обрабатывает его. Найдя подходящий маршрут, MvcRouteHandler вызывает сопоставленный маршруту обработчик. По умолчанию – это MvcHandler, который и создает и использует фабрику контроллеров.

Для получения класса фабрики контроллера MvcHandler использует класс ControllerBuilder (реализованный в виде singleton), который всегда содержит поле с экземпляром фабрики контроллеров. По умолчанию ControllerBuilder содержит и возвращает экземпляр класса DefaultControllerFactory. Однако разработчик может определить свою фабрику контроллеров простым кодом в global.asax:

protected void Application_Start()
{
  RegisterRoutes(RouteTable.Routes);
  ControllerBuilder.Current.SetControllerFactory(new ControllerFactory());
}


* This source code was highlighted with Source Code Highlighter.

где, ControllerFactory – это пользовательский класс фабрики контроллеров.

Итак, фабрика контроллеров, стандартная или определенная пользователем создана. После этого, у нее вызывается метод CreateController, которому передаются имя класса контроллера и контекст запроса, сформированный механизмом маршрутизации. На базе данных этих параметров фабрика должна вернуть экземпляр класса контроллера либо вызвать исключение.

При использовании стандартной фабрики контроллеров, в контексте запроса, кроме всего прочего может быть передан набор параметров маршрута RequestContext.RouteData.DataTokens, который может содержать наименования пространств имен (через значение параметра Namespaces), в которых следует искать класс контроллера. Это может быть полезными и может ускорить работу приложения, если в вашем проекте очень много пространств имен, а контроллеры ограничены только одним. Для подробностей ищите описание создания маршрутов.

Зачем и как определять свою фабрику контроллеров


В самом деле, переопределение фабрики контроллеров – это совершенно необязательное действие для создание проектов MVC Framework. Однако, разработчику может быть полезен инструмент управляющий созданием классов контроллеров.

Самым распространенным вариантом использования своей фабрики контроллеров является внедрение IoC/DI-контейнера, вроде Unity, для инстанцирования классов контроллера через контейнер. Надобность и потребность в IoC/DI-контейнере – это тема других статей, но если в проекте вы используете такие контейнеры, то переопределение фабрики контроллеров может стать для вас хорошим способом создавать контроллеры через контейнер. Описание такого внедрения можно посмотреть в этой статье, здесь я приведу только класс пользовательской фабрики контроллеров созданной с использованием Unity:
public class UnityControllerFactory : DefaultControllerFactory
{
  IUnityContainer _container;

  public UnityControllerFactory(IUnityContainer container)
  {
    _container = container;
  }

  protected override IController GetControllerInstance(Type controllerType)
  {
    if (controllerType == null)
      throw new ArgumentNullException("controllerType");

    if (!typeof(IController).IsAssignableFrom(controllerType))
      throw new ArgumentException(string.Format(
        "Type requested is not a controller: {0}", controllerType.Name),
        "controllerType");

    return _container.Resolve(controllerType) as IController;
  }
}


* This source code was highlighted with Source Code Highlighter.

Как вы видите новая фабрика контроллеров наследуется от DefaultControllerFactory и перегружает метод GetControllerInstance, который используется в DefaultControllerFactory для инстанцирования класса контроллера по его типу.

Другим вариантом использования фабрики контроллеров может стать внедрение “черных” и “белых” списков для контроллеров, которые можно или нельзя вызывать через клиентские запросы. Это может иметь смысл при создании крупного проекта с массой контроллеров, которые могут выводиться из употребления на время. Если вы реализуете фабрику контроллеров которая будет сверяться со “черными” и “белыми” списками, то вы решите легко проблему вывода контроллера из употребления еще на стадии его создания. Причем, для этого вам не потребуется ни редактировать код, ни создавать новые маршруты, ни перекомпилировать сборки или перезапускать приложение. Достаточно будет отредактировать “черный” или “белый” список, который может быть представлен хоть xml-файлом.

Точка


Мы рассмотрели как работает фабрика контроллеров. Важно усвоить следующее:
  • фабрика контроллеров вызывается из механизма маршрутизации;
  • фабрика контроллеров создает экземпляры классов контроллеров;
  • фабрику контроллеров можно переопределить, но это совершенно не обязательно;
  • свой экземпляр фабрики контроллеров лучше наследовать от базового класса DefaultControllerFactory для того, чтобы не нарушить работу механизма MVC Framework;
  • если вы используете IoC/DI-контейнеры, то фабрика контроллеров здорово поможет вам.
В следующей статье мы начнем рассматривать работу механизма ActionInvoker и сопутствующих атрибутов.

Progg it
Tags:
Hubs:
+20
Comments 9
Comments Comments 9

Articles