ASP.NET Web API 控制器创建过程(二)
ASP.NET Web API 控制器创建过程(二)
前言
本来这篇随笔应该是在上周就该写出来发布的,由于身体跟不上节奏感冒发烧有心无力,这种天气感冒发烧生不如死,也真正的体会到了什么叫病来如山倒,病去如抽丝。这两天状态才好了一点,让我理解了什么才是革命的本钱,希望大家也多保重身体。
好了,还是回归主题,对于上一篇的内容讲解的只是ASP.NET Web API控制器创建过程中的一个局部知识,在接着上篇内容讲解的之前,我会先回顾一下上篇的内容,并且在本篇里进行整合,让我们要看到的是一个整个的创建过程。
ASP.NET Web API 控制器创建、激活过程
- ASP.NET Web API 控制器创建过程(一)
- ASP.NET Web API 控制器创建过程(二)
创建、激活过程
图1

在前面的篇幅中我们说过APIController是由HttpControllerDispatcher类型来创建的,这只是表面上的,图1中显示的就是控制器创建的整个过程了,我们先来回顾一下上一篇所讲的,不然会觉得不连贯,在回顾的同时也会对图1进行讲解。
首先我们来分解图1,可以把图1中分为两个部分,
第一个部分就是HttpConfiguration类型所表示的部分。如图2
图2

先来解释一下HttpConfiguration部分,在HttpConfiguration类型中有两个属性,第一个是ServicesContainer类型的属性Services,第二个就是IDependencyResolver类型的属性DependencyResolver,对于Services属性的类型在上篇中我也说过了,就是一个IoC容器,从HttpConfiguration类型角度来看就是一个依赖注入到HttpConfiguration中的IoC容器,对于DependencyResolver属性来说也差不多就是这个意思了。
只不过Services这个容器中存放的大多都是ASP.NET Web API框架中做一些基础工作的类型。
就好像上篇中说到的,在ASP.NET Web API框架中加载控制器所在程序集的时候我们就是使用自定义的工作项替换掉了Services容器中的默认工作项:
selfHostServer.Configuration.Services.Replace(typeof(IAssembliesResolver),
new CustomAssembliesResolver.LoadSpecifiedAssembliesResolver());
这里从图2中可以看出默认的DefaultAssembliesResolver类型来执行这项工作的。
到这里也就是上个篇幅中的主要内容了。下面我们还是继续分解图1,上面说了第一部分了下面来看第二部分,第二个部分就是HttpControllerDispatcher类型到APIController类型的生成过程,也就是图1了。
首先我们的ASP.NET Web API框架会从HttpConfiguration中的Services容器中获取一个ControllerSelector(控制器选择器),这个控制器选择器呢对应的类型大家从图2中也可以看到,图1中也有,很明了。
那么ControllerSelector主要干什么呢?肯定是选择控制器阿,当然了根据请求选择相应的控制器是主要功能,次要功能是啥?次要功能是生成控制器缓存,不然从哪选阿对不。在ASP.NET MVC框架中控制器缓存是存在xml文件中的,现在很好奇在ASP.NET Web API框架中控制器缓存是什么样的存储方式呢?
我们就来看一下控制器选择器的次要功能。
控制器选择器次要功能
首先我们先说明一下缓存的类型为ConcurrentDictionary<string, HttpControllerDescriptor>类型,就是一个一一对应的键值队,string表示着控制器名称,而HttpControllerDescriptor表示着对应控制器的控制器描述类型,这个类型很重要稍后再说,我们先要了解ConcurrentDictionary<string, HttpControllerDescriptor>缓存的由来。
首先在我们控制器选择器实例化的时候,在控制器选择器的构造函数中已经使用了延迟加载技术对控制器缓存进行了创建,具体的创建过程可以在图1看到,是由DefaultAssembliesResolver类型(或者是我们自定义的工作项)加载指定的程序集,并且交由DefaultHttpControllerTypeResolver类型根据ASP.NET Web API框架中默认的搜索过滤条件返回加载程序集中的所有符合条件的控制器类型(ControllerTypes),来看示例。
所用项目结构还是上个篇幅的示例:
图3

图4

在图4中我们额外定义了一些控制器类型,然后在SelfHost端定义如下示例代码:
代码1-1
static void WriterControllerTypeMessage(HttpSelfHostServer selfHostServer)
{ ICollection<Type> types = selfHostServer.Configuration.Services.GetHttpControllerTypeResolver().GetControllerTypes(selfHostServer.Configuration.Services.GetAssembliesResolver());
foreach (Type type in types)
{
Console.WriteLine(type.Namespace + "_______" + type.Name);
}
}
并且在注册端调用此静态函数:
using (HttpSelfHostServer selfHostServer = new HttpSelfHostServer(selfHostConfiguration))
{
selfHostServer.Configuration.Routes.MapHttpRoute(
"DefaultApi", "api/{controller}/{id}", new { id = RouteParameter.Optional }); selfHostServer.Configuration.Services.Replace(typeof(IAssembliesResolver),
new CustomAssembliesResolver.LoadSpecifiedAssembliesResolver()); WriterControllerTypeMessage(selfHostServer); selfHostServer.OpenAsync();
Console.WriteLine("服务器端服务监听已开启");
Console.Read();
}
结果如图5:
图5

在我们获取了ControllerTypes过后了,ASP.NET Web API框架中有个HttpControllerTypeCache类型的对象就藏不住了,之前的一些操作都是由HttpControllerTypeCache类型去处理的,而在HttpControllerTypeCache获取了ControllerTypes过后就要做一个很重要的工作了,就是对ControllerTypes进行分组操作最后返回一个Dictionary<string, ILookup<string, Type>>类型的对象,就拿上面的示例来说吧,最后经过分组后的Dictionary<string, ILookup<string, Type>>类型值应该是:
Writer-->NameSpaceControllerOne->WriterController
NameSpaceControllerTwo->WriterController
Read-->NameSpaceControllerOne->ReadController
WriterAndRead-->NameSpaceControllerThree-> WriterAndReadController
Product-->WebAPIController->ProductController
这个时候的值并不是最终的缓存类型,而是通过我们的控制器选择器根据HttpControllerTypeCache类型所生成的Dictionary<string, ILookup<string, Type>>类型值来生成ConcurrentDictionary<string, HttpControllerDescriptor>缓存类型,还是根据上面的示例,我们看一下最后生成的缓存类型值。
修改1-1如下示例代码:
代码1-2
static void WriterControllerTypeMessage(HttpSelfHostServer selfHostServer)
{ ICollection<Type> types = selfHostServer.Configuration.Services.GetHttpControllerTypeResolver().GetControllerTypes(selfHostServer.Configuration.Services.GetAssembliesResolver());
foreach (Type type in types)
{
Console.WriteLine(type.Namespace + "_______" + type.Name);
} //Dictionary<string, ILookup<string, Type>> controllertypecache = types.GroupBy<Type, string>(t => t.Name, StringComparer.OrdinalIgnoreCase).ToDictionary<IGrouping<string, Type>, string, ILookup<string, Type>>
// (g => g.Key,
// g => g.ToLookup<Type, string>(t => (t.Namespace ?? string.Empty), StringComparer.OrdinalIgnoreCase), StringComparer.OrdinalIgnoreCase); //foreach (var value in controllertypecache)
//{
// foreach (var val in value.Value)
// { // }
//} IDictionary<string, HttpControllerDescriptor> mapping = selfHostServer.Configuration.Services.GetHttpControllerSelector().GetControllerMapping(); foreach (var meg in mapping)
{
Console.WriteLine("ControllerName:" + meg.Key + ".ControllerTypeName:" + meg.Value.ControllerType.Name);
} }
结果如图6:
图6

(在代码1-2中注释掉的部分就是可以查看对ControllerTypes进行分组操作返回Dictionary<string, ILookup<string, Type>>类型的值)。
控制器选择器主要功能
次要功能看完之后,主要功能想必大家也是很明了吧,在有了控制器缓存对象过后,控制器选择器则会根据HttpRequestMessage对象中的路由数据对象获取控制器名称,然后从缓存中获取到对应的HttpControllerDescriptor类型实例。
具体生成工作
在获取到了HttpControllerDescriptor类型实例过后生成IHttpController的工作就变得很简单了,还是从HttpConfiguration中的Services容器中获得对应的负责控制器生成激活的工作项,在图1中可以明确的看出是DefaultHttpControllerActivator类型,在DefaultHttpControllerActivator类型工作的时候它会从HttpConfiguration中获取DependencyResolver属性对应的容器,如果这里的情况不满足才会调用后面的TypeActivator来生成激活IHttpController(通过反射)。
作者:金源
出处:http://www.cnblogs.com/jin-yuan/
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面
ASP.NET Web API 控制器创建过程(二)的更多相关文章
- ASP.NET Web API 控制器创建过程(一)
ASP.NET Web API 控制器创建过程(一) 前言 在前面对管道.路由有了基础的了解过后,本篇将带大家一起学习一下在ASP.NET Web API中控制器的创建过程,这过程分为几个部分下面的内 ...
- ASP.NET Web API 控制器执行过程(一)
ASP.NET Web API 控制器执行过程(一) 前言 前面两篇讲解了控制器的创建过程,只是从框架源码的角度去简单的了解,在控制器创建过后所执行的过程也是尤为重要的,本篇就来简单的说明一下控制器在 ...
- ASP.NET Web API 控制器执行过程
http://www.cnblogs.com/jin-yuan/p/3952605.html
- ASP.NET Web API 过滤器创建、执行过程(二)
ASP.NET Web API 过滤器创建.执行过程(二) 前言 前面一篇中讲解了过滤器执行之前的创建,通过实现IFilterProvider注册到当前的HttpConfiguration里的服务容器 ...
- ASP.NET Web API 过滤器创建、执行过程(一)
ASP.NET Web API 过滤器创建.执行过程(一) 前言 在上一篇中我们讲到控制器的执行过程系列,这个系列要搁置一段时间了,因为在控制器执行的过程中包含的信息都是要单独的用一个系列来描述的,就 ...
- 使用ASP.NET Web API 2创建OData v4 终结点
开放数据协议(Open Data Protocol[简称OData])是用于Web的数据访问协议.OData提供了一种对数据集进行CRUD操作(Create,Read,Update,Delete)的统 ...
- 细说Asp.Net Web API消息处理管道(二)
在细说Asp.Net Web API消息处理管道这篇文章中,通过翻看源码和实例验证的方式,我们知道了Asp.Net Web API消息处理管道的组成类型以及Asp.Net Web API是如何创建消息 ...
- asp.net web api 控制器
1控制器操作的参数 控制器操作的参数可以是内置类型也可以是自定义类型,无参也是允许的. 2控制器操作返回值 类型 说明 void 操作返回值为void时,Web API返回空HTTP响应,其状态码为2 ...
- [转]使用ASP.NET Web API 2创建OData v4 终结点
本文转自:http://www.cnblogs.com/farb/p/ODataAspNetWebAPI.html 开放数据协议(Open Data Protocol[简称OData])是用于Web的 ...
随机推荐
- .Net Core MVC 网站开发(Ninesky) 2.4、添加栏目与异步方法
在2.3中完成依赖注入后,这次主要实现栏目的添加功能.按照前面思路栏目有三种类型,常规栏目即可以添加子栏目也可以选择是否添加内容,内容又可以分文章或其他类型,所以还要添加一个模块功能.这次主要实现栏目 ...
- [linux]阿里云主机的免登陆安全SSH配置与思考
公司服务器使用的第三方云端服务,即阿里云,而本地需要经常去登录到服务器做相应的配置工作,鉴于此,每次登录都要使用密码是比较烦躁的,本着极速思想,我们需要配置我们的免登陆. 一 理论概述 SSH介绍 S ...
- 菜鸟Python学习笔记第一天:关于一些函数库的使用
2017年1月3日 星期二 大一学习一门新的计算机语言真的很难,有时候连函数拼写出错查错都能查半天,没办法,谁让我英语太渣. 关于计算机语言的学习我想还是从C语言学习开始为好,Python有很多语言的 ...
- 在WPF中使用依赖注入的方式创建视图
在WPF中使用依赖注入的方式创建视图 0x00 问题的产生 互联网时代桌面开发真是越来越少了,很多应用都转到了浏览器端和移动智能终端,相应的软件开发上的新技术应用到桌面开发的文章也很少.我之前主要做W ...
- SQLServer文件收缩-图形化+命令
汇总篇:http://www.cnblogs.com/dunitian/p/4822808.html#tsql 收缩前 图形化演示: 不仅仅可以收缩日记文件,数据库文件也是可以收缩的,只不过日记收缩比 ...
- Minor【 PHP框架】1.简介
1.1 Minor是什么 Minor是一个简单但是优秀的符合PSR4的PHP框架,It just did what a framework should do. 只做一个框架应该做的,简单而又强大! ...
- ls: 无法访问/usr/sbin/smartctl: 没有那个文件或目录
环境:RHEL6.5 + Oracle 11.2.0.4 RAC 在安装RAC时,检查时缺少包 cvuqdisk-1.0.9-1,oracle提供脚本修复安装. 但在执行时报错: [root@orad ...
- AJAX实现登录界面
使用php跳转界面和AJAX都可实现登录界面的跳转的登录失败对的提醒.但是,php跳转的方式 需要额外加载其他界面,用户体验差.AJAX可实现当前页面只刷新需要的数据,不对当前网页进行 重新加载或者是 ...
- unity 3d 解析 json
官网案例传送门 我这里不过是借花献佛,案例官网就有. using UnityEngine; using System.Collections; public class json : MonoBeha ...
- 微信小程序教程汇总
目前市面上在内测期间出来的一些实战类教程还是很不错的,主要还是去快速学习小程序开发的整体流程,一个组件一个组件的讲的很可能微信小程序一升级,这个组件就变了,事实本就如此,谁让现在是内测呢.我们不怕,下 ...