天天看點

總體介紹ASP.NET Web API下Controller的激活與釋放流程一、HttpController激活流程二、HttpController的釋放

總體介紹ASP.NET Web API下Controller的激活與釋放流程一、HttpController激活流程二、HttpController的釋放

對于組成ASP.NET Web

API核心架構的消息處理管道來說,處于末端的HttpMessageHandler是一個HttpRoutingDispatcher對象。當它完成路由解析工作之後(HttpRoutingDispatcher的路由解析隻發生在Self

Host寄宿模式下,對于Web

Host寄宿模式來說,路由解析工作是由ASP.NET路由系統來完成的),在預設情況下它會将請求傳遞給一個HttpControllerDispatcher對象。

HttpControllerDispatcher實作了目标HttpController對象的激活與執行,并将代表執行結果的HttpResponseMessage對象傳回給HttpRoutingDispatcher對象,後者将此HttpResponseMessage回傳給消息管道進行相應處理後最終完成對請求的響應。

右圖所示的UML展現了激活HttpController的整個流程。當HttpControllerDispatcher接管請求之後,它會擷取注冊的HttpControllerSelector對象,并調用其SelectController方法得到描述目标HttpController的HttpControllerDescriptor對象。

預設注冊的HttpControllerSelector是一個DefaultHttpControllerSelector對象,後者借助于注冊的HttpControllerTypeResolver對象得到所有HttpController類型,進而建立一個描述這些HttpController的HttpControllerDescriptor對象與HttpController名稱之間的映射關系。當它的SelectController方法被執行後,它隻需要根據請求攜帶的HttpRouteData對象擷取目标HttpController的名稱,并從此映射關系中選擇對應的HttpControllerDescriptor即可。

HttpControllerDispatcher接下來調用這個HttpControllerDescriptor對象的CreateController方法得到激活的HttpController對象。對于這個HttpControllerDescriptor對象來說,當它的CreateController方法被調用之後,它會擷取注冊的HttpControllerActivator對象,并調用其Create方法實作針對目标HttpController對象的激活并将激活的對象傳回。

預設注冊的DefaultHttpControllerActivator對象會利用注冊的DependencyResolver根據HttpController類型去擷取代表目标HttpController執行個體的對象。如果後者傳回一個具體的HttpController對象,該對象将直接作為方法的傳回值,否則DefaultHttpControllerActivator直接采用反射的形式建立目标HttpController對象并傳回。

由于預設注冊的DependencyResolver是一個EmptyResolver對象,由它傳回的HttpController對象總是Null,是以在預設情況下激活的HttpController對象總是以反射的形式建立的。正因為如此,我們定義的HttpController類型必須具有一個預設構造函數。

我們知道作為自定義HttpController預設基類的ApiController類型實作了IDispoable接口,資源釋放工作可以通過調用實作的Dispose方法來完成,那麼這個方法是在什麼時候執行的呢?除此之外,我們知道表示請求的HttpRequestMessage類型具有一個字典類型的屬性Properties,我們可以利用它将任何一個對象附加到一個HttpRequestMessage對象上,如果這些附加對象需要實施資源釋放操作,這些操作又是在什麼時候被執行的呢?

實際上HttpRequestMessage通過Properties屬性表示的屬性字典為需要釋放的資源預留了存儲空間,對應的Key為“MS_DisposableRequestResources”,對應的值是一個List<IDisposable>的對象。我們可以調用HttpRequestMessage具有如下定義的擴充方法GetResourcesForDisposal得到這個清單,也可以調用擴充方法RegisterForDispose将一個或者多個類型實作了IDisposable接口的對象放到這個清單中。

ASP.NET Web API還為釋放這些附加到HttpRequestMessage上的對象定義了如上一個擴充方法DisposeRequestResources,那麼這個方法究竟是在什麼時候被調用的呢?

釋放這些資源的時機取決于采用的寄宿模式。對于Web Host來說,ASP.NET Web

API用于“處理請求、回複響應”的HttpMessageHandler管道是由HttpControllerHandler建立的,後者根據目前HTTP上下文建立一個表示目前請求的HttpRequestMessage對象并傳入這個管道進行處理。在整個管道完成對請求的處理并最終對請求予以響應之後,HttpControllerHandler會負責完成如下三項與資源釋放有關的工作。

調用HttpRequestMessage對象的擴充方法DisposeRequestResources釋放附加在自身屬性字典中的對象。

調用HttpRequestMessage對象的Dispose方法對請求消息本身作相應的釋放工作。

調用傳回的HttpResponseMessage對象對響應消息作相應的釋放工作。

當一個HttpMessage對象的Close或者Dispose方法被調用的時侯,被其封裝的HttpRequestMessage或者HttpResponseMessage會相應地得到釋放。對于請求消息來說,具體的資源釋放工作包括針對HttpRequestMessage自身的釋放和對附加到屬性字典中資源的釋放。

我們不妨通過一個簡單的執行個體來示範Self

Host寄宿模式下伴随着HttpMessage對象的釋放對被封裝的HttpRequestMessage對象的釋放。我們在一個控制台應用中定義了如下三個需要被釋放的類型Foo、Bar和Baz,它們共同的基類DisposableObject實作了IDisposable接口,并在實作Dispose方法中通過輸出一段文字以确定具體的釋放操作是否被執行。

然後我們再Main方法中編寫了如下一段簡短的程式。我們分别建立了類型為Foo、Bar和Baz的三個對象,并通過調用擴充方法RegisterForDispose将它們注冊到建立的HttpRequestMessage對象上。我們針對這個HttpRequestMessage對象利用反射的方式建立了一個HttpMessage對象,最終調用其Close方法對它作相應的釋放工作。

我們運作這段程式後會控制台上得到如下的輸出結果,由此可見通過調用擴充方法RegisterForDispose注冊到某個HttpRequestMessage對象上的資源能夠在它釋放的時候得到釋放。(S406)

對于ApiController來說,當它的ExecuteAsync方法被執行的時候,它會調用擴充方法RegisterForDispose将自己注冊到代表目前請求的HttpRequestMessage對象上。毫無疑問,ApiController對象的釋放會通過對這個HttpRequestMessage的釋放來完成。

作者:蔣金楠

微信公衆賬号:大内老A

如果你想及時得到個人撰寫文章以及著作的消息推送,或者想看看個人推薦的技術資料,可以掃描左邊二維碼(或者長按識别二維碼)關注個人公衆号(原來公衆帳号蔣金楠的自媒體将會停用)。

本文版權歸作者和部落格園共有,歡迎轉載,但未經作者同意必須保留此段聲明,且在文章頁面明顯位置給出原文連接配接,否則保留追究法律責任的權利。

<a href="http://www.cnblogs.com/artech/p/asp-net-web-api-active-release-controller.html" target="_blank">原文連結</a>

繼續閱讀