標籤:des style blog http color io os ar 使用
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), 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<string, HttpControllerDescriptor>類型,就是一個一一相應的鍵值隊,string表示著控制器名稱,而HttpControllerDescriptor表示著相應控制器的控制器描寫敘述類型,這個類型非常重要稍後再說,我們先要瞭解ConcurrentDictionary<string, HttpControllerDescriptor>緩衝的由來。
首先在我們控制器選取器執行個體化的時候,在控制器選取器的建構函式中已經使用了延遲載入技術對控制器緩衝進行了建立,詳細的建立過程能夠在圖1看到,是由DefaultAssembliesResolver類型(或者是我們自己定義的工作項目)載入指定的程式集,而且交由DefaultHttpControllerTypeResolver類型依據ASP.NET Web API架構中預設的搜尋過濾條件返回載入程式集中的全部合格控制器類型(ControllerTypes),來看示範範例。
所用項目結構還是上個篇幅的示範範例:
圖3
圖4
在圖4中我們額外定義了一些控制器類型,然後在SelfHost端定義例如以下示範範例代碼:
代碼1-1
staticvoidWriterControllerTypeMessage(HttpSelfHostServerselfHostServer) { ICollection<Type>types=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("server端服務監聽已開啟"); 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
staticvoidWriterControllerTypeMessage(HttpSelfHostServerselfHostServer) { ICollection<Type>types=selfHostServer.Configuration.Services.GetHttpControllerTypeResolver().GetControllerTypes(selfHostServer.Configuration.Services.GetAssembliesResolver()); foreach (Typetypeintypes) { 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 (varmeginmapping) { Console.WriteLine("ControllerName:"+meg.Key+".ControllerTypeName:"+meg.Value.ControllerType.Name); } }
結果6:
圖6
(在代碼1-2中凝視掉的部分就是能夠查看對ControllerTypes進行分組操作返回Dictionary<string, ILookup<string, Type>>類型的值)。
控制器選取器主要功能
次要功能看完之後,主要功能想必大家也是非常明了吧,在有了控制器緩衝對象過後,控制器選取器則會依據HttpRequestMessage對象中的路由資料對象擷取控制器名稱,然後從緩衝中擷取到相應的HttpControllerDescriptor類型執行個體。
詳細產生工作
在擷取到了HttpControllerDescriptor類型執行個體過後產生IHttpController的工作就變得非常easy了,還是從HttpConfiguration中的Services容器中獲得相應的負責控制器產生啟用的工作項目,在圖1中能夠明白的看出是DefaultHttpControllerActivator類型,在DefaultHttpControllerActivator類型工作的時候它會從HttpConfiguration中擷取DependencyResolver屬性相應的容器,假設這裡的情況不滿足才會調用後面的TypeActivator來產生啟用IHttpController(通過反射)。
金源
出處:http://blog.csdn.net/jinyuan0829
本文著作權歸作者和CSDN共同擁有,歡迎轉載,但未經作者允許必須保留此段聲明,且在文章頁面
ASP.NET Web API 控制器建立過程(二)