Внутри ASP.NET MVC: конвейер обработки запросов, часть четвёртая (фабрика контроллеров, введение)

Продолжим рассматривать условно разделённые части конвейера обработки запросов ASP.NET MVC, показанного в данной статье. В предыдущей статье была подробно описана вторая часть (обработчик запроса), а в этой речь пойдёт о третьей части - фабрике контроллеров. Ниже показана эта схема.



В прошлой статье мы остановились на методе BeginProcessRequest обработчика запроса MvcHandler. Напомню, что данный обработчик HTTP-данных реализует интрефейс IHttpAsyncHandler
#region IHttpAsyncHandler Members

IAsyncResult IHttpAsyncHandler.BeginProcessRequest(HttpContext context,
  AsyncCallback cb, object extraData)
{
  return BeginProcessRequest(context, cb, extraData);
}

void IHttpAsyncHandler.EndProcessRequest(IAsyncResult result)
{
  EndProcessRequest(result);
}
и следовательной выполняет код асинхронно. Внутренний метод BeginProcessRequest, который вызывается в конечном счёте и в котором создаётся фабрика контроллеров имеет следующую сигнатуру.
protected internal virtual IAsyncResult BeginProcessRequest(HttpContextBase httpContext,
  AsyncCallback callback, object state)
{
  IController controller;
  IControllerFactory factory;
  ProcessRequestInit(httpContext, out controller, out factory);

  IAsyncController asyncController = controller as IAsyncController;
  if(asyncController != null)
  {
    // asynchronous controller
    BeginInvokeDelegate beginDelegate =
      delegate(AsyncCallback asyncCallback, object asyncState)
    {
      try
      {
        return asyncController.BeginExecute(RequestContext, asyncCallback, asyncState);
      }
      catch
      {
        factory.ReleaseController(asyncController);
        throw;
      }
    };

    EndInvokeDelegate endDelegate = delegate(IAsyncResult asyncResult)
    {
      try
      {
        asyncController.EndExecute(asyncResult);
      }
      finally
      {
        factory.ReleaseController(asyncController);
      }
    };

    SynchronizationContext syncContext = 
      SynchronizationContextUtil.GetSynchronizationContext();
    AsyncCallback newCallback = 
      AsyncUtil.WrapCallbackForSynchronizedExecution(callback, syncContext);
    return AsyncResultWrapper.Begin(newCallback, 
      state, beginDelegate, endDelegate, _processRequestTag);
  }
  else
  {
    // synchronous controller
    Action action = delegate
    {
      try
      {
        controller.Execute(RequestContext);
      }
      finally
      {
        factory.ReleaseController(controller);
      }
    };

    return AsyncResultWrapper.BeginSynchronous(callback, state, action, _processRequestTag);
  }
}
В данной статье нас интересуют только эти три строки кода
IController controller;
IControllerFactory factory;
ProcessRequestInit(httpContext, out controller, out factory);
или точнее то, что они делают. И так, как видно из кода объявляются две пустые ссылки: IController и IControllerFactory. Первая будет в последующем указывать на объект контроллера, а вторая на объект фабрики контроллеров. После того как ссылки объявлены они передаются во внутренний метод ProcessRequestInit обработчика MvcHandler, в котором  будут проинициализированы.
private void ProcessRequestInit(HttpContextBase httpContext, 
  out IController controller, out IControllerFactory factory)
{
  HttpContext currentContext = HttpContext.Current;
  if(currentContext != null)
  {
    bool? isRequestValidationEnabled = ValidationUtility.IsValidationEnabled(currentContext);
    if(isRequestValidationEnabled == true)
    {
      ValidationUtility.EnableDynamicValidation(currentContext);
    }
  }

  AddVersionHeader(httpContext);
  RemoveOptionalRoutingParameters();

  // Get the controller type
  string controllerName = RequestContext.RouteData.GetRequiredString("controller");

  // Instantiate the controller and call Execute
  factory = ControllerBuilder.GetControllerFactory();
  controller = factory.CreateController(RequestContext, controllerName);
  if(controller == null)
  {
    throw new InvalidOperationException(
        String.Format(
            CultureInfo.CurrentCulture,
            MvcResources.ControllerBuilder_FactoryReturnedNull,
            factory.GetType(),
            controllerName));
  }
}
А создаётся объект фабрики и сам объект контроллера, как видно из высшеприведённого кода, всего лишь парой строкой кода.
factory = ControllerBuilder.GetControllerFactory();
controller = factory.CreateController(RequestContext, controllerName);
А вот на этом мы остановимся и рассмотрим процесс создания этих объектов намного подробно, но уже в отдельных статьях. Процесс создания экземпляра класса будет рассмотрен в статье посвещённой классу ControllerBuilder, а создание экземпляра контроллера в статье, где будет описан класс DefaultControllerFactory. Дело в том, что одной из важных точек расширения и изменения механизма обработки запросов в ASP.NET MVC являестя фабрика контроллеров (конечно же я не имею ввиду сам паттерн MVC, а только механизм обработки запросов). Безусловно таковыми также являютмя  обработчик маршрута и обработчик HTTP-данных, но они относятся к конвейеру ASP.NET в целом, нежели к ASP.NET MVC. А вот сама фабрика контроллеров уже тесно привязана к механизму обработки запросов в стиле ASP.NET MVC.