真实的国产乱ⅩXXX66竹夫人,五月香六月婷婷激情综合,亚洲日本VA一区二区三区,亚洲精品一区二区三区麻豆

成都創(chuàng)新互聯(lián)網(wǎng)站制作重慶分公司

ASP.NETWebAPI控制器執(zhí)行過(guò)程(一)-創(chuàng)新互聯(lián)

ASP.NET Web API 控制器執(zhí)行過(guò)程(一)

目前成都創(chuàng)新互聯(lián)公司已為1000+的企業(yè)提供了網(wǎng)站建設(shè)、域名、網(wǎng)頁(yè)空間、網(wǎng)站托管、服務(wù)器托管、企業(yè)網(wǎng)站設(shè)計(jì)、淶水網(wǎng)站維護(hù)等服務(wù),公司將堅(jiān)持客戶(hù)導(dǎo)向、應(yīng)用為本的策略,正道將秉承"和諧、參與、激情"的文化,與客戶(hù)和合作伙伴齊心協(xié)力一起成長(zhǎng),共同發(fā)展。

前言

前面兩篇講解了控制器的創(chuàng)建過(guò)程,只是從框架源碼的角度去簡(jiǎn)單的了解,在控制器創(chuàng)建過(guò)后所執(zhí)行的過(guò)程也是尤為重要的,本篇就來(lái)簡(jiǎn)單的說(shuō)明一下控制器在創(chuàng)建過(guò)后將會(huì)做哪些工作。

ASP.NET Web API 控制器執(zhí)行過(guò)程

ASP.NET Web API 控制器執(zhí)行過(guò)程(一)

ASP.NET Web API 控制器執(zhí)行過(guò)程(二)

控制器執(zhí)行過(guò)程

我們知道控制器的生成過(guò)程都是在HttpControllerDispatcher類(lèi)型中來(lái)操作的,那我們要想知道控制器在創(chuàng)建過(guò)后執(zhí)行操作的入口點(diǎn)也必須在HttpControllerDispatcher類(lèi)型中才能發(fā)現(xiàn)。來(lái)看如下示例代碼:

代碼1-1

   privateTaskSendAsyncInternal(HttpRequestMessagerequest, CancellationTokencancellationToken)
   {
        IHttpRouteDatarouteData=request.GetRouteData();
        HttpControllerDescriptordescriptor=this.ControllerSelector.SelectController(request);     
        IHttpControllercontroller=descriptor.CreateController(request);    
        HttpConfigurationconfiguration=request.GetConfiguration();
        HttpControllerContextcontrollerContext=newHttpControllerContext(descriptor.Configuration, routeData, request) {
            Controller=controller,
            ControllerDescriptor=descriptor
        };
        returncontroller.ExecuteAsync(controllerContext, cancellationToken);
}

看過(guò)前面兩篇的朋友看到這里的代碼一定會(huì)很熟悉了,控制器的生成過(guò)程就包含在了其中,在代碼1-1中我們會(huì)看到HttpControllerContext類(lèi)型,從它的名稱(chēng)來(lái)看想必大家也都知道了它的作用,代表著進(jìn)入控制器處理階段的邏輯上的上下文對(duì)象,并且封裝著一些很重要的信息。

HttpControllerContext控制器上下文

示例代碼1-2

publicclassHttpControllerContext
   {
        publicHttpControllerContext();
        publicHttpControllerContext(HttpConfigurationconfiguration, IHttpRouteDatarouteData, HttpRequestMessagerequest);
 
        publicHttpConfigurationConfiguration { get; set; }
        publicIHttpControllerController { get; set; }
        publicHttpControllerDescriptorControllerDescriptor { get; set; }
        publicHttpRequestMessageRequest { get; set; }
        publicIHttpRouteDataRouteData { get; set; }
}

結(jié)合代碼1-2和代碼1-1可以看到在HttpControllerContext類(lèi)型中對(duì)HttpConfiguration類(lèi)型的對(duì)象,它的重要性不用多說(shuō)了,里面包含著很多配置信息以及存放基礎(chǔ)設(shè)施的容器對(duì)象,然后就是路由數(shù)據(jù)對(duì)象IHttpRouteData類(lèi)型,以及最后的Http請(qǐng)求對(duì)象HttpRequestMessage類(lèi)型的對(duì)象,并且在代碼1-1中對(duì)HttpControllerContext類(lèi)型中的Controller和ControllerDescriptor屬性進(jìn)行了賦值,Controller屬性對(duì)應(yīng)的就是當(dāng)前被創(chuàng)建好的控制器,而ControllerDescriptor屬性則是表示Controller屬性對(duì)應(yīng)控制器的描述類(lèi)型,現(xiàn)在回頭再看一下HttpControllerContext類(lèi)型的對(duì)象就知道它里面包含的內(nèi)容是有多重要了。

現(xiàn)在我們?cè)倩氐酱a1-1中,最后我們看到是由IHttpController類(lèi)型的變量controller調(diào)用方法ExecuteAsync()方法由此進(jìn)入控制器中,一般控制器都是繼承自ApiController,我們就從ApiController類(lèi)型來(lái)入手。

ApiController類(lèi)型

示例代碼1-3

   publicabstractclassApiController : IHttpController, IDisposable
   {
        publicvirtualTaskExecuteAsync(HttpControllerContextcontrollerContext, CancellationTokencancellationToken);
}

在代碼1-3中我們可以看到再ApiController類(lèi)型中定義了ExecuteAsync()方法,ApiController為抽象類(lèi)型,控制器的主要執(zhí)行過(guò)程也就是都在ExecuteAsync()方法中,下面我看一下具體的實(shí)現(xiàn),如下示例代碼。

代碼1-4

publicvirtualTaskExecuteAsync(HttpControllerContextcontrollerContext, CancellationTokencancellationToken)
   {
        HttpControllerDescriptorcontrollerDescriptor=controllerContext.ControllerDescriptor;
        ServicesContainercontrollerServices=controllerDescriptor.Configuration.Services;
        HttpActionDescriptoractionDescriptor=controllerServices.GetActionSelector().SelectAction(controllerContext);
        HttpActionContextactionContext=newHttpActionContext(controllerContext, actionDescriptor);
        FilterGroupinggrouping=newFilterGrouping(actionDescriptor.GetFilterPipeline());
        IEnumerableactionFilters=grouping.ActionFilters;
        IEnumerableauthorizationFilters=grouping.AuthorizationFilters;
        IEnumerableexceptionFilters=grouping.ExceptionFilters;
        returnInvokeActionWithExceptionFilters(InvokeActionWithAuthorizationFilters(actionContext, cancellationToken, authorizationFilters, ()=>actionDescriptor.ActionBinding.ExecuteBindingAsync(actionContext, cancellationToken).Then(delegate {
            this._modelState=actionContext.ModelState;
            returnInvokeActionWithActionFilters(actionContext, cancellationToken, actionFilters, () =>controllerServices.GetActionInvoker().InvokeActionAsync(actionContext, cancellationToken))();
        }, newCancellationToken(), false))(), actionContext, cancellationToken, exceptionFilters);
}

代碼1-4中定義了控制器的執(zhí)行過(guò)程,我們就從源碼的角度去了解一下控制器的執(zhí)行過(guò)程。

在代碼1-4中先是從控制器上下文對(duì)象中獲取當(dāng)前控制器類(lèi)型的描述對(duì)象HttpControllerDescriptor類(lèi)型的實(shí)例,而后從HttpControllerDescriptor類(lèi)型實(shí)例從獲取在HttpConfiguration中的服務(wù)容器ServicesContainer類(lèi)型的實(shí)例,對(duì)于這些類(lèi)型前面的篇幅或多或少的講過(guò)了。

在這之后從服務(wù)容器中獲取IHttpActionSelector類(lèi)型的行為選擇器并且經(jīng)過(guò)篩選獲取到最佳匹配的HttpActionDescriptor類(lèi)型,在之前也有講到過(guò)HttpControllerDescriptor,這里的HttpActionDescriptor跟其相似,就是表示控制其行為(方法)的元數(shù)據(jù)信息。

下面我就來(lái)講解一下控制器行為選擇器的執(zhí)行過(guò)程,也就是它篩選方法的幾個(gè)步驟。

首先我們要知道控制器行為選擇器的類(lèi)型,從代碼1-4中可以看到是通過(guò)服務(wù)容器對(duì)象的擴(kuò)展方法來(lái)獲取的,在前面的篇幅也都講過(guò)了,這里可以得知我們要查看的控制器行為選擇器的類(lèi)型就是ApiControllerActionSelector類(lèi)型。

ApiControllerActionSelector控制器行為選擇器

示例代碼1-5

   publicclassApiControllerActionSelector : IHttpActionSelector
   {
        //Fields
        privatereadonlyobject_cacheKey;
        privateActionSelectorCacheItem_fastCache;
        privateconststringActionRouteKey="action";
        privateconststringControllerRouteKey="controller";
 
        //Methods
        publicApiControllerActionSelector();
        publicvirtualILookupGetActionMapping(HttpControllerDescriptorcontrollerDescriptor);
        privateActionSelectorCacheItemGetInternalSelector(HttpControllerDescriptorcontrollerDescriptor);
        publicvirtualHttpActionDescriptorSelectAction(HttpControllerContextcontrollerContext);
 
        //Nested Types
        privateclassActionSelectorCacheItem
        {
        }
 
        privateclassLookupAdapter : ILookup, IEnumerable>, IEnumerable
        {
        }
}

從代碼1-5中我們可以看到ApiControllerActionSelector類(lèi)型中包含著兩個(gè)私有類(lèi),這兩個(gè)私有類(lèi)后面會(huì)有講到起到的作用也很重要。

下面我們還是回到代碼1-4中的邏輯,從調(diào)用控制器行為選擇器中調(diào)用SelectAction()方法開(kāi)始。

在ApiControllerActionSelector類(lèi)型中調(diào)用SelectAction()時(shí),實(shí)際是由SelectAction()方法調(diào)用GetInternalSelector()方法生成一個(gè)控制器方法的緩存對(duì)象,也就是ApiControllerActionSelector類(lèi)型的私有類(lèi)ActionSelectorCacheItem,而真正的篩選工作都是由它來(lái)執(zhí)行的,所以下面才是介紹的重點(diǎn)。

控制器方法選擇器-篩選方法的步驟

1初始化篩選

在ActionSelectorCacheItem類(lèi)型的初始化的時(shí)候, ActionSelectorCacheItem實(shí)例中會(huì)首先根據(jù)HttpControllerDescriptor對(duì)象獲取到控制器本身的類(lèi)型,然后利用反射的技術(shù)根據(jù)條件獲取到當(dāng)前控制器類(lèi)型中的所有方法,最后保存為MethodInfo[]。而所謂的條件就是(BindingFlags.Public 、BindingFlags.Instance、方法所屬類(lèi)型必須是ApiController類(lèi)型的)。

我們看下ActionSelectorCacheItem類(lèi)型中的字段信息,這些字段里存放的都是很重要的數(shù)據(jù),后面會(huì)一一說(shuō)明。

示例代碼1-6

        privatereadonlyReflectedHttpActionDescriptor[] _actionDescriptors;
        privatereadonlyILookup_actionNameMapping;
        privatereadonlyIDictionary_actionParameterNames=newDictionary();
        privatereadonlyHttpMethod[] _cacheListVerbKinds=newHttpMethod[] { HttpMethod.Get, HttpMethod.Put, HttpMethod.Post };
        privatereadonlyReflectedHttpActionDescriptor[][] _cacheListVerbs;
        privatereadonlyHttpControllerDescriptor_controllerDescriptor;

1.1基礎(chǔ)信息初始化-ReflectedHttpActionDescriptor[] _actionDescriptors

這個(gè)時(shí)候初始化工作并沒(méi)有做完,這時(shí)候會(huì)把MethodInfo[]數(shù)組中的每個(gè)MethodInfo實(shí)例封裝成ReflectedHttpActionDescriptor類(lèi)型的對(duì)象,對(duì)于類(lèi)型稍后再說(shuō)。在封裝成ReflectedHttpActionDescriptor類(lèi)型的對(duì)象后,也會(huì)將每個(gè)實(shí)例存至一個(gè)ReflectedHttpActionDescriptor類(lèi)型的數(shù)組中。

1.2 基礎(chǔ)信息初始化-IDictionary_actionParameterNames

在1.1的工作做完之后呢,就會(huì)對(duì)每個(gè)ReflectedHttpActionDescriptor類(lèi)型的對(duì)象進(jìn)行分析,分析啥?分析方法的參數(shù)名稱(chēng),并且已1:n的方式存在IDictionary類(lèi)型的鍵值隊(duì)中。這里存放的值就是一個(gè)方法描述對(duì)象作為key值,value值是這個(gè)方法的所有參數(shù)名稱(chēng)。

1.3 基礎(chǔ)信息初始化-ILookup _actionNameMapping

這里的工作是根據(jù)1.1工作的結(jié)果,利用_actionDescriptors變量來(lái)根據(jù)ActionName分組,而最后_actionNameMapping中的值也是集合類(lèi)型,不過(guò)每一項(xiàng)中的值都是個(gè)1:n的鍵值隊(duì)值。因?yàn)榭刂破鞣椒赡艽嬖谥剌d的情況。

1.4 基礎(chǔ)信息初始化-ReflectedHttpActionDescriptor[][]_cacheListVerbs

_cacheListVerbs值的初始化在最后,它的定義是一個(gè)二維數(shù)組,數(shù)組初始確定為三行N列,三行的控制是由_cacheListVerbKinds值控制的,這里初始化的是根據(jù)1.1工作的結(jié)果將_actionDescriptors值按Http方法類(lèi)型進(jìn)行分類(lèi),所以我說(shuō)的是三行N列。

上面的這些步驟雖然有點(diǎn)煩,不過(guò)了解一下便于下面的理解。

2. Action名稱(chēng)篩選

示例代碼1-7

public HttpActionDescriptor SelectAction(HttpControllerContext controllerContext)

在ActionSelectorCacheItem類(lèi)型的SelectAction()方法中,將會(huì)進(jìn)行剩下的幾個(gè)篩選步驟,首先是會(huì)從方法的參數(shù)controllerContext中獲取到路由數(shù)據(jù)對(duì)象,并且在其Values屬性中查詢(xún)是否有“Action”鍵對(duì)應(yīng)的方法名稱(chēng)值,這個(gè)時(shí)候就會(huì)出現(xiàn)下面兩種情況。

2.1如果注冊(cè)的路由中有Action名稱(chēng)

這這種情況下會(huì)把上面1.3中的工作成果拿來(lái),_actionNameMapping根據(jù)Action名稱(chēng)獲取到一個(gè)ReflectedHttpActionDescriptor類(lèi)型的數(shù)組,這個(gè)數(shù)組在整個(gè)流程中還不能往下走,還要經(jīng)過(guò)篩選,篩選的規(guī)則是判斷ReflectedHttpActionDescriptor中支持的Http方法類(lèi)型是否支持當(dāng)前請(qǐng)求的Http方法類(lèi)型。

這里就涉及到在ReflectedHttpActionDescriptor類(lèi)型的內(nèi)部對(duì)IActionHttpMethodProvider類(lèi)型特性的處理,不多說(shuō)后面的文章會(huì)講到。這里上一張圖大家先留個(gè)印象。

圖1

ASP.NET Web API 控制器執(zhí)行過(guò)程(一)

2.2沒(méi)有路由名稱(chēng)的根據(jù)Http方法類(lèi)型

在這種情況下,則是根據(jù)代碼1-7中的方法的方法參數(shù)controllerContext中獲取當(dāng)前的請(qǐng)求類(lèi)型,然后從1.4的工作結(jié)果中用_cacheListVerbs值根據(jù)當(dāng)前請(qǐng)求的Http方法類(lèi)型獲取到ReflectedHttpActionDescriptor類(lèi)型的數(shù)組實(shí)例。

3.根據(jù)請(qǐng)求參數(shù)名稱(chēng)、數(shù)量來(lái)匹配

3.1有參數(shù)的情況下

在這種情況下,會(huì)先把路由數(shù)據(jù)對(duì)象的Values屬性中的Keys值存放在一個(gè)集合A中,然后再獲取當(dāng)前請(qǐng)求的查詢(xún)字符串集合,并且把集合中的所有Key值添加到集合A中,這就使的所有請(qǐng)求的參數(shù)名稱(chēng)都在一個(gè)集合中,然后就會(huì)從1.2的結(jié)果中根據(jù)當(dāng)前的ReflectedHttpActionDescriptor類(lèi)型實(shí)例(這里是接著2的流程,所以這里是ReflectedHttpActionDescriptor類(lèi)型的數(shù)組遍歷執(zhí)行)從_actionParameterNames獲取對(duì)應(yīng)的參數(shù)名稱(chēng)數(shù)組,然后是集合A會(huì)和獲取的參數(shù)名稱(chēng)數(shù)組做一一的比較,看看集合A中是否包含參數(shù)名稱(chēng),如果都有了則是滿(mǎn)足條件。

這里返回的依然可能是ReflectedHttpActionDescriptor類(lèi)型的數(shù)組,因?yàn)樵谝粋€(gè)方法有重載時(shí),比如說(shuō)Get(stringa)和Get(string a,string b)兩個(gè)方法時(shí),請(qǐng)求中如果有a和b兩個(gè)參數(shù)的話(huà),Get(string a)也是滿(mǎn)足條件的。

3.2無(wú)參數(shù)的情況下

這種情況下就比較簡(jiǎn)單了,從1.2的結(jié)果中還如上述那般,遍歷的根據(jù)ReflectedHttpActionDescriptor類(lèi)型實(shí)例獲取參數(shù)名稱(chēng)數(shù)組,找到數(shù)組長(zhǎng)度為0的。

4. 排除IActionMethodSelector類(lèi)型特性的控制器方法

到最后一個(gè)篩選條件了,還是遍歷ReflectedHttpActionDescriptor類(lèi)型數(shù)組中的每一項(xiàng),并且查找他們是否有使用實(shí)現(xiàn)了IActionMethodSelector接口的特性。

4.1有使用了實(shí)現(xiàn)IActionMethodSelector接口的特性

在這種情況下,會(huì)獲取到IActionMethodSelector類(lèi)型,并且調(diào)用其實(shí)現(xiàn)方法IsValidForRequest(),如果返回true的話(huà)這個(gè)ReflectedHttpActionDescriptor類(lèi)型才可以被使用,這也是提供給我們自定義實(shí)現(xiàn)的一個(gè)便捷,通常情況下是下面的這種情況。

4.2沒(méi)有使用實(shí)現(xiàn)IActionMethodSelector接口的特性

在這種情況下,會(huì)添加ReflectedHttpActionDescriptor類(lèi)型到返回實(shí)例的集合中。

最后控制器行為選擇器只會(huì)返回ReflectedHttpActionDescriptor類(lèi)型集合的中的第一項(xiàng)且必須是只有一項(xiàng),其他情況都會(huì)拋出異常。

這個(gè)時(shí)候思緒回到代碼1-4,看到HttpActionDescriptor(ReflectedHttpActionDescriptor)類(lèi)型變量被賦值,回想下上面的過(guò)程,感覺(jué)過(guò)了好久一樣。

最后貼一下很粗略的示意圖

圖2

ASP.NET Web API 控制器執(zhí)行過(guò)程(一)

我們上面所講的也不過(guò)只是在整個(gè)過(guò)程中的第一步過(guò)程。

另外有需要云服務(wù)器可以了解下創(chuàng)新互聯(lián)scvps.cn,海內(nèi)外云服務(wù)器15元起步,三天無(wú)理由+7*72小時(shí)售后在線(xiàn),公司持有idc許可證,提供“云服務(wù)器、裸金屬服務(wù)器、高防服務(wù)器、香港服務(wù)器、美國(guó)服務(wù)器、虛擬主機(jī)、免備案服務(wù)器”等云主機(jī)租用服務(wù)以及企業(yè)上云的綜合解決方案,具有“安全穩(wěn)定、簡(jiǎn)單易用、服務(wù)可用性高、性?xún)r(jià)比高”等特點(diǎn)與優(yōu)勢(shì),專(zhuān)為企業(yè)上云打造定制,能夠滿(mǎn)足用戶(hù)豐富、多元化的應(yīng)用場(chǎng)景需求。


網(wǎng)頁(yè)標(biāo)題:ASP.NETWebAPI控制器執(zhí)行過(guò)程(一)-創(chuàng)新互聯(lián)
瀏覽路徑:http://weahome.cn/article/cssogo.html

其他資訊

在線(xiàn)咨詢(xún)

微信咨詢(xún)

電話(huà)咨詢(xún)

028-86922220(工作日)

18980820575(7×24)

提交需求

返回頂部