HTML5技术

ASP.NET Core MVC 源码学习:详解 Action 的匹配 - Savorboard(2)

字号+ 作者:H5之家 来源:H5之家 2017-03-30 18:02 我要评论( )

ApplicationModel 里面关于 Controller 的包装是一个 IListControllerModel,看一下 ControllerModel 的定义: public class ControllerModel : ICommonModel, IFilterModel, IApiExplorerModel{//......public ILi

ApplicationModel 里面关于 Controller 的包装是一个 IList<ControllerModel>,看一下 ControllerModel 的定义:

public class ControllerModel : ICommonModel, IFilterModel, IApiExplorerModel { //...... public IList<ActionModel> Actions { get; } public ApiExplorerModel ApiExplorer { get; set; } public ApplicationModel Application { get; set; } public IReadOnlyList<object> Attributes { get; } MemberInfo ICommonModel.MemberInfo => ControllerType; string ICommonModel.Name => ControllerName; public string ControllerName { get; set; } public TypeInfo ControllerType { get; } public IList<PropertyModel> ControllerProperties { get; } public IList<IFilterMetadata> Filters { get; } public IDictionary<string, string> RouteValues { get; } public IDictionary<object, object> Properties { get; } public IList<SelectorModel> Selectors { get; } }

在 ASP.NET Core MVC 框架中,ApplicationModel 有下面几个提供者,他们用于初始化整个 ApplicationModel 的各个部分,我们还是分别看一下吧。

AuthorizationApplicationModelProvider: 处理认证相关业务逻辑,在它的Executing方法中会将 AuthorizeFilter,AllowAnonymousFilter 等过滤器添加到 ApplicationModelProviderContext 里面的 ApplicationModel 里。

DefaultApplicationModelProvider:初始化 ControllerModel, 添加 Controller 相关的各种信息,添加用户自定义 Filter,遍历 ControllerTypes : 创建 ControllerModel --> 初始化Properties --> 初始化Parameters。

CorsApplicationModelProvider:跨域资源相关逻辑,添加CorsAuthorizationFilterFactory,DisableCorsAuthorizationFilter,CorsAuthorizationFilterFactory,DisableCorsAuthorizationFilter等过滤器。

TempDataApplicationModelProvider: 添加 SaveTempDataPropertyFilterFactory 过滤器,存储Controller中的TempData信息,注意 TempDataAttribute 修饰的属性只能是基元类型或字符串。

构建ApplicationModel

MVC 框架通过 ControllerActionDescriptorProvider 中的 BuildModel() 这个方法进行 ApplicationModel 的构建:

internal protected ApplicationModel BuildModel() { var controllerTypes = GetControllerTypes(); var context = new ApplicationModelProviderContext(controllerTypes); for (var i = 0; i < _applicationModelProviders.Length; i++) { _applicationModelProviders[i].OnProvidersExecuting(context); } for (var i = _applicationModelProviders.Length - 1; i >= 0; i--) { _applicationModelProviders[i].OnProvidersExecuted(context); } return context.Result; }

现在,我们已经有一个完整的 ApplicationModel 对象了。

有了 ApplicationModel 对象之后,会再进行一次约定的应用。比如以下Action重写路由的情况或者配置多个路由的情况。

2、ActionDescriptorCollection是怎么创建的?

ControllerActionDescriptor构建

ControllerActionDescriptor的构建是基于ApplicationModel对象的,下面我就画了一个流程图用来展示构建 ControllerActionDescriptor 的整个过程,就不过多描述了。

截止到目前,我们会得到一个 IEnumerable<ControllerActionDescriptor> 集合对象。

在有了 ControllerActionDescriptor 之后,ActionDescriptorCollectionProvider 会提供一个属性,

public ActionDescriptorCollection ActionDescriptors { get { if (_collection == null) { UpdateCollection(); } return _collection; } }

在这个属性中使用了 UpdateCollection 这个方法来更新 ActionDescriptorCollection。

private void UpdateCollection() { var context = new ActionDescriptorProviderContext(); for (var i = 0; i < _actionDescriptorProviders.Length; i++) { _actionDescriptorProviders[i].OnProvidersExecuting(context); } for (var i = _actionDescriptorProviders.Length - 1; i >= 0; i--) { _actionDescriptorProviders[i].OnProvidersExecuted(context); } _collection = new ActionDescriptorCollection( new ReadOnlyCollection<ActionDescriptor>(context.Results), Interlocked.Increment(ref _version)); }

OK , 现在我们有了 ActionDescriptorCollection , 之后的流程就比较简单了,但是会涉及到几个算法。

接下来,轮到 ActionSelectorDecisionTreeProvider 上场了,它主要是把 ActionDescriptorCollection,组装成为一个 IActionSelectionDecisionTree 对象以便于后续的查找匹配工作, IActionSelectionDecisionTree 的数据结构是一个多叉树,组装过程是使用了一个深度优先的递归算法。

我们回到起点,继续看这张图:

现在 SelectCandidates 你应该能够看懂了:

public IReadOnlyList<ActionDescriptor> SelectCandidates(RouteContext context) { //IActionSelectionDecisionTree 对象 var tree = _decisionTreeProvider.DecisionTree; //使用的是一个多叉树查找算法,关于算法可以看我这篇博文: //http://www.cnblogs.com/savorboard/p/6582399.html return tree.Select(context.RouteData.Values); }

接下来就是 SelectBestCandidates 这个流程:

1、遍历 Action 列表,评估 Action 的相关约束,返回匹配的 ActionDescriptor 列表。

 

1.本站遵循行业规范,任何转载的稿件都会明确标注作者和来源;2.本站的原创文章,请转载时务必注明文章作者和来源,不尊重原创的行为我们将追究责任;3.作者投稿可能会经我们编辑修改或补充。

相关文章
  • 车大棒浅谈jQuery源码(二) - 车大棒

    车大棒浅谈jQuery源码(二) - 车大棒

    2017-04-02 10:07

  • ASP.NET Core MVC 源码学习:MVC 启动流程详解 - Savorboard

    ASP.NET Core MVC 源码学习:MVC 启动流程详解 - Savorboard

    2017-03-27 18:01

  • 车大棒浅谈jQuery源码(一) - 车大棒

    车大棒浅谈jQuery源码(一) - 车大棒

    2017-03-27 09:00

  • vue2源码浏览分析01 - 小结巴巴吧

    vue2源码浏览分析01 - 小结巴巴吧

    2017-03-21 09:00

网友点评
<