扫二维码与项目经理沟通
我们在微信上24小时期待你的声音
解答本文疑问/技术咨询/运营咨询/技术建议/互联网交流
ASP.NET Web API 控制器创建过程(二)
成都创新互联公司专注为客户提供全方位的互联网综合服务,包含不限于成都做网站、网站制作、兰山网络推广、重庆小程序开发、兰山网络营销、兰山企业策划、兰山品牌公关、搜索引擎seo、人物专访、企业宣传片、企业代运营等,从售前售中售后,我们都将竭诚为您服务,您的肯定,是我们大的嘉奖;成都创新互联公司为所有大学生创业者提供兰山建站搭建服务,24小时服务热线:18982081108,官方网址:www.cdcxhl.com前言
本来这篇随笔应该是在上周就该写出来发布的,由于身体跟不上节奏感冒发烧有心无力,这种天气感冒发烧生不如死,也真正的体会到了什么叫病来如山倒,病去如抽丝。这两天状态才好了一点,让我理解了什么才是革命的本钱,希望大家也多保重身体。
好了,还是回归主题,对于上一篇的内容讲解的只是ASP.NET Web API控制器创建过程中的一个局部知识,在接着上篇内容讲解的之前,我会先回顾一下上篇的内容,并且在本篇里进行整合,让我们要看到的是一个整个的创建过程。
ASP.NET Web API 控制器创建、激活过程
l ASP.NET Web API 控制器创建过程(一)
l 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), newCustomAssembliesResolver.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
首先在我们控制器选择器实例化的时候,在控制器选择器的构造函数中已经使用了延迟加载技术对控制器缓存进行了创建,具体的创建过程可以在图1看到,是由DefaultAssembliesResolver类型(或者是我们自定义的工作项)加载指定的程序集,并且交由DefaultHttpControllerTypeResolver类型根据ASP.NET Web API框架中默认的搜索过滤条件返回加载程序集中的所有符合条件的控制器类型(ControllerTypes),来看示例。
所用项目结构还是上个篇幅的示例:
图3
图4
在图4中我们额外定义了一些控制器类型,然后在SelfHost端定义如下示例代码:
代码1-1
staticvoidWriterControllerTypeMessage(HttpSelfHostServerselfHostServer) { ICollectiontypes=selfHostServer.Configuration.Services.GetHttpControllerTypeResolver().GetControllerTypes(selfHostServer.Configuration.Services.GetAssembliesResolver()); foreach (Typetypeintypes) { Console.WriteLine(type.Namespace+"_______"+type.Name); } }
并且在注册端调用此静态函数:
using (HttpSelfHostServerselfHostServer=newHttpSelfHostServer(selfHostConfiguration)) { selfHostServer.Configuration.Routes.MapHttpRoute( "DefaultApi", "api/{controller}/{id}", new { id=RouteParameter.Optional }); selfHostServer.Configuration.Services.Replace(typeof(IAssembliesResolver), newCustomAssembliesResolver.LoadSpecifiedAssembliesResolver()); WriterControllerTypeMessage(selfHostServer); selfHostServer.OpenAsync(); Console.WriteLine("服务器端服务监听已开启"); Console.Read(); }
结果如图5:
图5
在我们获取了ControllerTypes过后了,ASP.NET Web API框架中有个HttpControllerTypeCache类型的对象就藏不住了,之前的一些操作都是由HttpControllerTypeCache类型去处理的,而在HttpControllerTypeCache获取了ControllerTypes过后就要做一个很重要的工作了,就是对ControllerTypes进行分组操作最后返回一个Dictionary
Writer-->NameSpaceControllerOne->WriterController
NameSpaceControllerTwo->WriterController
Read-->NameSpaceControllerOne->ReadController
WriterAndRead-->NameSpaceControllerThree->WriterAndReadController
Product-->WebAPIController->ProductController
这个时候的值并不是最终的缓存类型,而是通过我们的控制器选择器根据HttpControllerTypeCache类型所生成的Dictionary
修改1-1如下示例代码:
代码1-2
staticvoidWriterControllerTypeMessage(HttpSelfHostServerselfHostServer) { ICollectiontypes=selfHostServer.Configuration.Services.GetHttpControllerTypeResolver().GetControllerTypes(selfHostServer.Configuration.Services.GetAssembliesResolver()); foreach (Typetypeintypes) { Console.WriteLine(type.Namespace+"_______"+type.Name); } //Dictionary > controllertypecache = types.GroupBy (t => t.Name,StringComparer.OrdinalIgnoreCase).ToDictionary , string, ILookup > // (g => g.Key, // g => g.ToLookup (t => (t.Namespace ?? string.Empty),StringComparer.OrdinalIgnoreCase), StringComparer.OrdinalIgnoreCase); //foreach(var value in controllertypecache) //{ // foreach (var val in value.Value) // { // } //} IDictionary mapping=selfHostServer.Configuration.Services.GetHttpControllerSelector().GetControllerMapping(); foreach (varmeginmapping) { Console.WriteLine("ControllerName:"+meg.Key+".ControllerTypeName:"+meg.Value.ControllerType.Name); } }
结果如图6:
图6
(在代码1-2中注释掉的部分就是可以查看对ControllerTypes进行分组操作返回Dictionary
控制器选择器主要功能
次要功能看完之后,主要功能想必大家也是很明了吧,在有了控制器缓存对象过后,控制器选择器则会根据HttpRequestMessage对象中的路由数据对象获取控制器名称,然后从缓存中获取到对应的HttpControllerDescriptor类型实例。
具体生成工作
在获取到了HttpControllerDescriptor类型实例过后生成IHttpController的工作就变得很简单了,还是从HttpConfiguration中的Services容器中获得对应的负责控制器生成激活的工作项,在图1中可以明确的看出是DefaultHttpControllerActivator类型,在DefaultHttpControllerActivator类型工作的时候它会从HttpConfiguration中获取DependencyResolver属性对应的容器,如果这里的情况不满足才会调用后面的TypeActivator来生成激活IHttpController(通过反射)。
另外有需要云服务器可以了解下创新互联scvps.cn,海内外云服务器15元起步,三天无理由+7*72小时售后在线,公司持有idc许可证,提供“云服务器、裸金属服务器、高防服务器、香港服务器、美国服务器、虚拟主机、免备案服务器”等云主机租用服务以及企业上云的综合解决方案,具有“安全稳定、简单易用、服务可用性高、性价比高”等特点与优势,专为企业上云打造定制,能够满足用户丰富、多元化的应用场景需求。
我们在微信上24小时期待你的声音
解答本文疑问/技术咨询/运营咨询/技术建议/互联网交流