现在我们从代码角度来看下,从消息处理管道末尾是怎么创建出Controller实例的。消息处理管道末端是一个叫HttpRoutingDispatcher的处理器,其内部完成路由后 ,会把消息派送给其内部的一个消息处理器HttpControllerDispatcher来完成Controller实例创建。
一、流程示意图
二、代码说明
我们先看下HttpControllerDispatcher代码,主要看下SendAsync方法:
public class HttpControllerDispatcher : HttpMessageHandler { private readonly HttpConfiguration _configuration; private IExceptionLogger _exceptionLogger; private IExceptionHandler _exceptionHandler; private IHttpControllerSelector _controllerSelector; /// <summary> /// Initializes a new instance of the <see cref="HttpControllerDispatcher"/> class. /// </summary> public HttpControllerDispatcher(HttpConfiguration configuration) { if (configuration == null) { throw Error.ArgumentNull("configuration"); } _configuration = configuration; } /// <summary> /// Gets the <see cref="HttpConfiguration"/>. /// </summary> public HttpConfiguration Configuration { get { return _configuration; } } /// <remarks>This property is internal and settable only for unit testing purposes.</remarks> internal IExceptionLogger ExceptionLogger { get { if (_exceptionLogger == null) { _exceptionLogger = ExceptionServices.GetLogger(_configuration); } return _exceptionLogger; } set { _exceptionLogger = value; } } /// <remarks>This property is internal and settable only for unit testing purposes.</remarks> internal IExceptionHandler ExceptionHandler { get { if (_exceptionHandler == null) { _exceptionHandler = ExceptionServices.GetHandler(_configuration); } return _exceptionHandler; } set { _exceptionHandler = value; } } //从服务容器里直接获取默认的HttpControllerSelector private IHttpControllerSelector ControllerSelector { get { if (_controllerSelector == null) { _controllerSelector = _configuration.Services.GetHttpControllerSelector(); } return _controllerSelector; } } protected override async Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken) { if (request == null) { throw Error.ArgumentNull("request"); } ExceptionDispatchInfo exceptionInfo; HttpControllerContext controllerContext = null; try { //1.通过IHttpControllerSelector获取HttpControllerDescriptor HttpControllerDescriptor controllerDescriptor = ControllerSelector.SelectController(request); if (controllerDescriptor == null) { return request.CreateErrorResponse( HttpStatusCode.NotFound, Error.Format(SRResources.ResourceNotFound, request.RequestUri), SRResources.NoControllerSelected); } //2.HttpControllerDescriptor的CreateController方法创建出控制器实例 IHttpController controller = controllerDescriptor.CreateController(request); if (controller == null) { return request.CreateErrorResponse( HttpStatusCode.NotFound, Error.Format(SRResources.ResourceNotFound, request.RequestUri), SRResources.NoControllerCreated); } //准备参数ControllerContext controllerContext = CreateControllerContext(request, controllerDescriptor, controller); //3.直接执行控制器的ExecuteAsync,即抽象类ApiController里的ExecuteAsync方法 return await controller.ExecuteAsync(controllerContext, cancellationToken); } catch (OperationCanceledException) { // Propogate the canceled task without calling exception loggers or handlers. throw; } catch (HttpResponseException httpResponseException) { return httpResponseException.Response; } catch (Exception exception) { exceptionInfo = ExceptionDispatchInfo.Capture(exception); } Debug.Assert(exceptionInfo.SourceException != null); ExceptionContext exceptionContext = new ExceptionContext( exceptionInfo.SourceException, ExceptionCatchBlocks.HttpControllerDispatcher, request) { ControllerContext = controllerContext, }; await ExceptionLogger.LogAsync(exceptionContext, cancellationToken); HttpResponseMessage response = await ExceptionHandler.HandleAsync(exceptionContext, cancellationToken); if (response == null) { exceptionInfo.Throw(); } return response; } private static HttpControllerContext CreateControllerContext( HttpRequestMessage request, HttpControllerDescriptor controllerDescriptor, IHttpController controller) { Contract.Assert(request != null); Contract.Assert(controllerDescriptor != null); Contract.Assert(controller != null); HttpConfiguration controllerConfiguration = controllerDescriptor.Configuration; // Set the controller configuration on the request properties HttpConfiguration requestConfig = request.GetConfiguration(); if (requestConfig == null) { request.SetConfiguration(controllerConfiguration); } else { if (requestConfig != controllerConfiguration) { request.SetConfiguration(controllerConfiguration); } } HttpRequestContext requestContext = request.GetRequestContext(); // if the host doesn't create the context we will fallback to creating it. if (requestContext == null) { requestContext = new RequestBackedHttpRequestContext(request) { // we are caching controller configuration to support per controller configuration. Configuration = controllerConfiguration, }; // if the host did not set a request context we will also set it back to the request. request.SetRequestContext(requestContext); } return new HttpControllerContext(requestContext, request, controllerDescriptor, controller); } private static HttpConfiguration EnsureNonNull(HttpConfiguration configuration) { if (configuration == null) { throw Error.ArgumentNull("configuration"); } return configuration; } }
从SendAsync方法可以知道,主要有三大关键代码:
1、通过IHttpControllerSelector获取HttpControllerDescriptor
HttpControllerDescriptor controllerDescriptor = ControllerSelector.SelectController(request);
ControllerSelector是从服务容器里获取的默认实现DefaultHttpControllerSelector,回顾下里边的代码:
由Lazy特点,触发InitializeControllerInfoCache方法
进入HttpControllerTypeCache,读取缓存,由Lazy特点,触发InitializeCache
通过AssemblieResolver和HttpControllerTypeResolver组件构建出合法的控制器类型列表
执行HttpControllerTypeCache获取Cache后,根据其构建出控制器描述符缓存,SelectController方法直接从该缓存中获取最后的控制器描述符
2、HttpControllerDescriptor的CreateController方法创建出控制器实例
IHttpController controller = controllerDescriptor.CreateController(request);
使用HttpControllerDescriptor的CreateController方法创建
内部调用了组件DefaultHttpControllerActivator实现
3、直接执行控制器实例的ExecuteAsync,即抽象类ApiController里的ExecuteAsync方法
//准备参数ControllerContext
controllerContext = CreateControllerContext(request, controllerDescriptor, controller);
return await controller.ExecuteAsync(controllerContext, cancellationToken);
到这里就进入ApiController 的ExecuteAsync
//主要方法,创建控制器对象后,会调用ExecuteAsync方法,进行后续操作,由于还没讲控制器的创建,里边的逻辑以后再细说 public virtual Task<HttpResponseMessage> ExecuteAsync(HttpControllerContext controllerContext, CancellationToken cancellationToken) { if (_initialized) { // 如果已经创建过该实例,就抛出异常,一个控制器实例,多次请求不能重复使用 throw Error.InvalidOperation(SRResources.CannotSupportSingletonInstance, typeof(ApiController).Name, typeof(IHttpControllerActivator).Name); } Initialize(controllerContext); if (Request != null) { //先注册到待销毁集合,待请求完成后一起销毁改控制器实例 Request.RegisterForDispose(this); } HttpControllerDescriptor controllerDescriptor = controllerContext.ControllerDescriptor; ServicesContainer controllerServices = controllerDescriptor.Configuration.Services; //选择Action HttpActionDescriptor actionDescriptor = controllerServices.GetActionSelector().SelectAction(controllerContext); ActionContext.ActionDescriptor = actionDescriptor; if (Request != null) { Request.SetActionDescriptor(actionDescriptor); } FilterGrouping filterGrouping = actionDescriptor.GetFilterGrouping(); //ActionFilters IActionFilter[] actionFilters = filterGrouping.ActionFilters; //身份认证过滤器 IAuthenticationFilter[] authenticationFilters = filterGrouping.AuthenticationFilters; //授权过滤器 IAuthorizationFilter[] authorizationFilters = filterGrouping.AuthorizationFilters; //ExceptionFilters IExceptionFilter[] exceptionFilters = filterGrouping.ExceptionFilters; IHttpActionResult result = new ActionFilterResult(actionDescriptor.ActionBinding, ActionContext, controllerServices, actionFilters); if (authorizationFilters.Length > 0) { result = new AuthorizationFilterResult(ActionContext, authorizationFilters, result); } if (authenticationFilters.Length > 0) { result = new AuthenticationFilterResult(ActionContext, this, authenticationFilters, result); } if (exceptionFilters.Length > 0) { IExceptionLogger exceptionLogger = ExceptionServices.GetLogger(controllerServices); IExceptionHandler exceptionHandler = ExceptionServices.GetHandler(controllerServices); result = new ExceptionFilterResult(ActionContext, exceptionFilters, exceptionLogger, exceptionHandler, result); } //执行IHttpActionResult的ExecuteAsync return result.ExecuteAsync(cancellationToken); }