在理清路由的工作流程后, 接下来需要考虑的, 是 MVC 框架如何生成 Controller 以及它的生成时机.
根据以前 ASP.NET MVC 的经验, Controller 应该是由一个 ControllerFactory 构建的. 查看 ASP.NET Core MVC 的源码, 果然是有一个 DefaultControllerFactory 类, 并且不出意外的, 它拥有一个 CreateController 方法.
- public virtual object CreateController(ControllerContext context)
- {
- ...
- var controller = _controllerActivator.Create(context);
- foreach (var propertyActivator in _propertyActivators)
- {
- propertyActivator.Activate(context, controller);
- }
- return controller;
- }
但细推其使用的场合, 只出现在 ControllerFactoryProvider 的构造方法内部, 且仅是用于判断所传入的 controllerFactory 类型是否是 DefaultControllerFactory.
- public ControllerFactoryProvider(
- IControllerActivatorProvider activatorProvider,
- IControllerFactory controllerFactory,
- IEnumerable<IControllerPropertyActivator> propertyActivators)
- {
- ...
- _activatorProvider = activatorProvider;
- // Compat: Delegate to the IControllerFactory if it's not the default implementation.
- if (controllerFactory.GetType() != typeof(DefaultControllerFactory))
- {
- _factoryCreateController = controllerFactory.CreateController;
- _factoryReleaseController = controllerFactory.ReleaseController;
- }
- _propertyActivators = propertyActivators.ToArray();
- }
再看 ControllerFactoryProvider 内部的 CreateControllerFactory 方法. 这更像是一个真正创建 Controller 的工厂方法.
- public Func<ControllerContext, object> CreateControllerFactory(ControllerActionDescriptor descriptor)
- {
- ...
- if (_factoryCreateController != null)
- {
- return _factoryCreateController;
- }
- var controllerActivator = _activatorProvider.CreateActivator(descriptor);
- var propertyActivators = GetPropertiesToActivate(descriptor);
- object CreateController(ControllerContext controllerContext)
- {
- var controller = controllerActivator(controllerContext);
- for (var i = 0; i <propertyActivators.Length; i++)
- {
- var propertyActivator = propertyActivators[i];
- propertyActivator(controllerContext, controller);
- }
- return controller;
- }
- return CreateController;
- }
创建方式分为两种, 一种是使用自定义的工厂方法, 另一种是通过 ControllerActivatorProvider 的 CreateActivator 方法.
- public Func<ControllerContext, object> CreateActivator(ControllerActionDescriptor descriptor)
- {
- ...
- var controllerType = descriptor.ControllerTypeInfo?.AsType();
- ...
- if (_controllerActivatorCreate != null)
- {
- return _controllerActivatorCreate;
- }
- var typeActivator = ActivatorUtilities.CreateFactory(controllerType, Type.EmptyTypes);
- return controllerContext => typeActivator(controllerContext.HttpContext.RequestServices, arguments: null);
- }
明白了如何创建 Controller, 下面开始调查创建 Controller 的时机.
ControllerFactoryProvider 类的 CreateControllerFactory 方法是被 ControllerActionInvokerCache 类的 GetCachedResult 方法调用.
- public (ControllerActionInvokerCacheEntry cacheEntry, IFilterMetadata[] filters) GetCachedResult(ControllerContext controllerContext)
- {
- var cache = CurrentCache;
- var actionDescriptor = controllerContext.ActionDescriptor;
- IFilterMetadata[] filters;
- if (!cache.Entries.TryGetValue(actionDescriptor, out var cacheEntry))
- {
- var filterFactoryResult = FilterFactory.GetAllFilters(_filterProviders, controllerContext);
- filters = filterFactoryResult.Filters;
- var parameterDefaultValues = ParameterDefaultValues
- .GetParameterDefaultValues(actionDescriptor.MethodInfo);
- var objectMethodExecutor = ObjectMethodExecutor.Create(
- actionDescriptor.MethodInfo,
- actionDescriptor.ControllerTypeInfo,
- parameterDefaultValues);
- var controllerFactory = _controllerFactoryProvider.CreateControllerFactory(actionDescriptor);
- var controllerReleaser = _controllerFactoryProvider.CreateControllerReleaser(actionDescriptor);
- var propertyBinderFactory = ControllerBinderDelegateProvider.CreateBinderDelegate(
- _parameterBinder,
- _modelBinderFactory,
- _modelMetadataProvider,
- actionDescriptor);
- var actionMethodExecutor = ActionMethodExecutor.GetExecutor(objectMethodExecutor);
- cacheEntry = new ControllerActionInvokerCacheEntry(
- filterFactoryResult.CacheableFilters,
- controllerFactory,
- controllerReleaser,
- propertyBinderFactory,
- objectMethodExecutor,
- actionMethodExecutor);
- cacheEntry = cache.Entries.GetOrAdd(actionDescriptor, cacheEntry);
- }
- else
- {
- // Filter instances from statically defined filter descriptors + from filter providers
- filters = FilterFactory.CreateUncachedFilters(_filterProviders, controllerContext, cacheEntry.CachedFilters);
- }
- return (cacheEntry, filters);
- }
其值作为 ControllerActionInvokerCacheEntry 对象的一部分被方法返回.
GetCachedResult 方法的上层调用者是 ControllerActionInvokerProvider 类的 OnProvidersExecuting 方法.
- public void OnProvidersExecuting(ActionInvokerProviderContext context)
- {
- ...
- if (context.ActionContext.ActionDescriptor is ControllerActionDescriptor)
- {
- var controllerContext = new ControllerContext(context.ActionContext);
- // PERF: These are rarely going to be changed, so let's go copy-on-write.
- controllerContext.ValueProviderFactories = new CopyOnWriteList<IValueProviderFactory>(_valueProviderFactories);
- controllerContext.ModelState.MaxAllowedErrors = _maxModelValidationErrors;
- var cacheResult = _controllerActionInvokerCache.GetCachedResult(controllerContext);
- var invoker = new ControllerActionInvoker(
- _logger,
- _diagnosticSource,
- controllerContext,
- cacheResult.cacheEntry,
- cacheResult.filters);
- context.Result = invoker;
- }
- }
ControllerActionInvokerCacheEntry 对象又被作为 ControllerActionInvoker 对象的一部分为 ActionInvokerProviderContext 的 Result 属性赋值.
再往上跟踪, 到了 ActionInvokerFactory 类的 CreateInvoker 方法.
- public IActionInvoker CreateInvoker(ActionContext actionContext)
- {
- var context = new ActionInvokerProviderContext(actionContext);
- foreach (var provider in _actionInvokerProviders)
- {
- provider.OnProvidersExecuting(context);
- }
- for (var i = _actionInvokerProviders.Length - 1; i>= 0; i--)
- {
- _actionInvokerProviders[i].OnProvidersExecuted(context);
- }
- return context.Result;
- }
而它的调用者便是 MvcRouteHandler 或者 MvcAttributeRouteHandler.
- public Task RouteAsync(RouteContext context)
- {
- ...
- context.Handler = (c) =>
- {
- var routeData = c.GetRouteData();
- var actionContext = new ActionContext(context.HttpContext, routeData, actionDescriptor);
- if (_actionContextAccessor != null)
- {
- _actionContextAccessor.ActionContext = actionContext;
- }
- var invoker = _actionInvokerFactory.CreateInvoker(actionContext);
- if (invoker == null)
- {
- throw new InvalidOperationException(
- Resources.FormatActionInvokerFactory_CouldNotCreateInvoker(
- actionDescriptor.DisplayName));
- }
- return invoker.InvokeAsync();
- };
- ...
- }
到了这里创建 Controller 的工厂方法还没有被实际调用, 此时 Controller 还是不存在的. 所以还需要完成执行 ControllerActionInvoker 的 InvokeAsync 方法, 或者更准确地说是其基类 ResourceInvoker 的 InvokeAsync 方法.
- public virtual async Task InvokeAsync()
- {
- try
- {
- ...
- using (_logger.ActionScope(_actionContext.ActionDescriptor))
- {
- ...
- try
- {
- await InvokeFilterPipelineAsync();
- }
- ...
- }
- }
- ...
- }
从 InvokeFilterPipelineAsync 方法开始, 一系列的处理流程将依据不同状态逐步展开.
- private async Task InvokeFilterPipelineAsync()
- {
- var next = State.InvokeBegin;
- var scope = Scope.Invoker;
- var state = (object)null;
- var isCompleted = false;
- while (!isCompleted)
- {
- await Next(ref next, ref scope, ref state, ref isCompleted);
- }
- }
而到了 State.ActionBegin 这一步 (ControllerActionInvoker 类的 Next 方法), 终于能找到 Controller 工厂方法被执行的场合.
- private Task Next(ref State next, ref Scope scope, ref object state, ref bool isCompleted)
- {
- switch (next)
- {
- case State.ActionBegin:
- {
- var controllerContext = _controllerContext;
- _cursor.Reset();
- _instance = _cacheEntry.ControllerFactory(controllerContext);
- _arguments = new Dictionary<string, object>(StringComparer.OrdinalIgnoreCase);
- var task = BindArgumentsAsync();
- if (task.Status != TaskStatus.RanToCompletion)
- {
- next = State.ActionNext;
- return task;
- }
- goto case State.ActionNext;
- }
- ...
- }
- }
- }
最后以一张流程图总结上面的探寻过程.
来源: https://www.cnblogs.com/kenwoo/p/9496297.html