.NET Core开发日志——Controller
在理清的工作流程后,接下来需要考虑的,是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; } ... } } }
最后以一张流程图总结上面的探寻过程。