国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 學院 > 開發設計 > 正文

ASP.NET Web API的Controller是如何被創建的?

2019-11-17 01:52:54
字體:
來源:轉載
供稿:網友

asp.net Web API的Controller是如何被創建的?

Web API調用請求的目標是定義在某個HttpController類型中的某個Action方法,所以消息處理管道最終需要激活目標HttpController對象。調用請求的URI會攜帶目標HttpController的名稱,該名稱經過路由解析之后會作為路由變量保存到一個HttPRouteData對象中,而后者會被添加到代表當前請求的HttpRequestMessage對象的屬性字典中。ASP.NET Web API據此解析出目標HttpController的類型,進而實現針對目標HttpController實例的激活。[本文已經同步到《How ASP.NET Web API Works?》]

目錄一、程序集的解析二、HttpController類型的解析 1、DefaultHttpControllerTypeResolver 2、HttpController類型的緩存三、HttpController的選擇 1、DefaultHttpControllerSelector 2、獲取目標HttpController的名稱 3、建立HttpController名稱與HttpControllerDescriptor之間的映射 4、根據請求選擇HttpController四、HttpController的創建 1、HttpControllerActivator 2、DefaultHttpControllerActivator 3、DependencyResolver 4、HttpRequestMessage中的DependencyResolver 5、DependencyResolver在DefaultHttpControllerActivator中的應用一、程序集的解析在ASP.NET Web API的HttpController激活系統中,AssembliesResolver為目標HttpController類型解析提供候選的程序集。換句話說,候選HttpController類型的選擇范圍僅限于定義在由AssembliesResolver提供的程序集中的所有實現了IHttpController接口的類型。所有的AssembliesResolver均實現了接口IAssembliesResolver,該接口定義在命名空間“System.Web.Http.Dispatcher”下,如果未作特別說明,本節新引入的類型均定義在此命名空間下。如下面的代碼片斷所示,IAssembliesResolver接口中僅僅定義了一個唯一的GetAssemblies方法,該方法返回的正是提供的程序集列表。 1: public interface IAssembliesResolver 2: { 3: ICollection<Assembly> GetAssemblies(); 4: }默認使用的AssembliesResolver類型為DefaultAssembliesResolver。如下面的代碼片斷所示,DefaultAssembliesResolver在實現的GetAssemblies方法中直接返回當前應用程序域加載的所有程序集列表。 1: public class DefaultAssembliesResolver : IAssembliesResolver 2: { 3: public virtual ICollection<Assembly> GetAssemblies() 4: { 5: return AppDomain.CurrentDomain.GetAssemblies().ToList<Assembly>(); 6: } 7: }DefaultAssembliesResolver是默認使用的AssembliesResolver,那么默認的AssembliesResolver類型在ASP.NET Web API是如何確定的呢?要回答這個問題,需要涉及到另一個重要的類型ServicesContainer,它定義在命名空間“System.Web.Http.Controllers”下。由于DefaultAssembliesResolver在為HttpController類型解析提供的程序集僅限于當前應用程序域已經加載的程序集,如果目標HttpController定義在尚未加載的程序集中,我們不得不預先加載它們。但是這樣的問題只會發生在Self Host寄宿模式下,如果采用Web Host寄宿模式則無此困擾,原因在于后者默認使用的是另一個AssembliesResolver類型。我們知道在Web Host寄宿模式下用于配置ASP.NET Web API消息處理管道的是通過類型GlobalConfiguration的靜態只讀屬性Configuration返回的HttpConfiguration對象。從如下的代碼片斷我們可以發現,當GlobalConfiguration的Configuration屬性被第一次訪問的時候,在ServicesContainer中注冊的AssembliesResolver會被替換成一個類型為WebHostAssembliesResolver的對象。 1: public static class GlobalConfiguration 2: { 3: //其他成員 4: static GlobalConfiguration() 5: { 6: _configuration = new Lazy<HttpConfiguration>(delegate 7: { 8: HttpConfiguration configuration = new HttpConfiguration( new HostedHttpRouteCollection(RouteTable.Routes)); 9: configuration.Services.Replace(typeof(IAssembliesResolver), new WebHostAssembliesResolver()); 10: //其他操作 11: return configuration; 12: }); 13: //其他操作 14: } 15: 16: public static HttpConfiguration Configuration 17: { 18: get 19: { 20: return _configuration.Value; 21: } 22: } 23: }WebHostAssembliesResolver是一個定義在程序集“System.Web.Http.WebHost.dll”中的內部類型。從如下的代碼片斷可以看出WebHostAssembliesResolver在實現的GetAssemblies方法中直接通過調用BuildManager的GetReferencedAssemblies方法來獲取最終提供的程序集。 1: internal sealed class WebHostAssembliesResolver : IAssembliesResolver 2: { 3: ICollection<Assembly> IAssembliesResolver.GetAssemblies() 4: { 5: return BuildManager.GetReferencedAssemblies().OfType<Assembly>().ToList<Assembly>(); 6: } 7: }由于BuildManager的GetReferencedAssemblies方法幾乎返回了在運行過程中需要的所有程序集,如果我們將HttpController類型定義在單獨的程序集中,我們只要確保該程序集已經正常部屬就可以了。如果有人對此感興趣,可以試著將上面演示的實例從Self Host寄宿模式轉換成Web Host寄宿模式,看看ASP.NET Web API的HttpController激活系統能否正常解析出分別定義在Foo.dll、Bar.dll和Baz.dll中的HttpController類型。二、HttpController類型的解析注冊在當前ServicesContainer上的AssembliesResolver對象為HttpController類型的解析提供了可供選擇的程序集,真正用于解析HttpController類型的是一個名為HttpControllerTypeResolver的對象。所有的HttpControllerTypeResolver類型均實現了接口IHttpControllerTypeResolver,如下面的代碼片斷所示,定義其中的唯一方法GetControllerTypes借助于提供的AssembliesResolver解析出所有的HttpController類型。 1: public interface IHttpControllerTypeResolver 2: { 3: ICollection<Type> GetControllerTypes(IAssembliesResolver assembliesResolver); 4: }與AssembliesResolver注冊方式類似,默認使用的HttpControllerTypeResolver同樣是注冊在當前HttpConfiguration的ServicesContainer對象上。我們可以通過ServicesContainer具有如下定義的擴展方法GetHttpControllerTypeResolver得到這個注冊的HttpControllerTypeResolver對象。 1: public static class ServicesExtensions 2: { 3: //其他成員 4: public static IHttpControllerTypeResolver GetHttpControllerTypeResolver(this ServicesContainer services); 5: }我們同樣可以通過HttpConfiguration默認采用的DefaultServices的構造函數得到默認注冊的HttpControllerTypeResolver對象的類型。如下面的代碼片斷所示,這個默認注冊的HttpControllerTypeResolver是一個類型為DefaultHttpControllerTypeResolver的對象。 1: public class DefaultServices : ServicesContainer 2: { 3: //其他成員 4: public DefaultServices(HttpConfiguration configuration) 5: { 6: //其他操作 7: this.SetSingle<IHttpControllerTypeResolver>(new DefaultHttpControllerTypeResolver()); 8: } 9: }1、DefaultHttpControllerTypeResolver如下面的代碼片斷所示, DefaultHttpControllerTypeResolver具有一個Predicate<Type>類型的只讀屬性IsControllerTypePredicate,返回的委托對象用于判斷指定的類型是否是一個有效的HttpController類型。 1: public class DefaultHttpControllerTypeResolver : IHttpControllerTypeResolver 2: { 3: public DefaultHttpControllerTypeResolver(); 4: public DefaultHttpControllerTypeResolver(Predicate<Type> predicate); 5: 6: public virtual ICollection<Type> GetControllerTypes(IAssembliesResolver assembliesResolver); 7: 8: protected Predicate<Type> IsControllerTypePredicate { get; } 9: }如果我們具有特別的HttpController類型有效性驗證規則,可以在調用構造函數實例化DefaultHttpControllerTypeResolver對象時通過參數指定這個Predicate<Type>委托對象。在默認情況下,這個自動初始化的Predicate<Type>對象體現了默認采用的HttpController類型有效驗證規則。具體來說,默認情況下一個給定的類型必須同時滿足如下的條件才是一個有效的HttpController類型。是一個外部可見(IsVisible = true)的實例(IsAbstract = false)類(IsClass = true)。類型直接或者間接實現了接口IHttpController。類型名稱必須以“Controller”為后綴,但是不區分大小寫(可以使用“controller”作為后綴)。用于提供所有有效HttpController類型的GetControllerTypes方法的實現邏輯其實很簡單。它通過指定的AssembliesResolver得到一個程序集列表,對于定義在這些程序集中的所有類型,如果滿足上述的要求就是返回的HttpController類型之一。定義在類型DefaultHttpControllerTypeResolver中的針對有效HttpController類型的解析邏輯基本上體現在如下所示的代碼中。 1: public class DefaultHttpControllerTypeResolver : IHttpControllerTypeResolver 2: { 3: //其他成員 4: public virtual ICollection<Type> GetControllerTypes(IAssembliesResolver assembliesResolver) 5: { 6: List<Type> types = new List<Type>(); 7: foreach (Assembly assembly in assembliesResolver.GetAssemblies()) 8: { 9: foreach (Type type in assembly.GetTypes()) 10: { 11: if (this.IsControllerTypePredicate(type)) 12: { 13: types.Add(type); 14: } 15: } 16: } 17: return types; 18: } 19: }2、HttpController類型的緩存由于針對所有HttpController類型的解析需要大量使用到反射,這是一個相對耗時的過程,所以ASP.NET Web API會對解析出來的HttpController類型進行緩存。具體的緩存實現在具有如下定義的HttpControllerTypeCache類型中,這是一個定義在程序集“System.Web.Http.dll”中的內部類型。 1: internal sealed class HttpControllerTypeCache 2: { 3: //其他成員 4: internal Dictionary<string, ILookup<string, Type>> Cache { get; } 5: }緩存的HttpController類型通過只讀屬性Cache獲取,這是一個類型為Dictionary<string, ILookup<string, Type>>的字典對象。該字典的Key表示HttpController的名稱(HttpController類型名稱去除“Controller”后綴),其Value返回的ILookup<string, Type>對象包含一組具有相同名稱的HttpController類型列表,自身的Key表示HttpController類型的命名空間。三、目標HttpController的選擇AssembliesResolver僅僅是將所有合法的HttpController類型解析出來,針對具體的調用請求,系統必須從中選擇一個與當前請求匹配的HttpController類型出來。HttpController的選擇通過HttpControllerSelector對象來完成,所有的HttpControllerSelector類型均實現了具有如下定義的接口IHttpControllerSelector。 1: public interface IHttpControllerSelector 2: { 3: IDictionary<string, HttpControllerDescriptor> GetControllerMapping(); 4: HttpControllerDescriptor SelectController(HttpRequestMessage request); 5: }如上面的代碼片斷所示,該接口中定義了GetControllerMapping和SelectController兩個方法。GetControllerMapping返回一個描述所有HttpController類型的HttpControllerDescriptor對象與對應的HttpController名稱之間的映射關系。針對請求的HttpController選擇實現在SelectController方法中,它返回描述目標HttpController的HttpControllerDescriptor對象。1、DefaultHttpControllerSelector默認使用HttpControllerSelector依然注冊到當前的ServicesContainer對象中,我們可以調用ServicesContainer如下所示的擴展方法GetHttpControllerSelector得到注冊的HttpCont
發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
主站蜘蛛池模板: 东光县| 集安市| 余庆县| 明水县| 利川市| 勃利县| 金塔县| 丁青县| 安乡县| 莎车县| 江西省| 海丰县| 老河口市| 农安县| 巩义市| 蕉岭县| 子洲县| 济南市| 郁南县| 盖州市| 类乌齐县| 曲阳县| 甘谷县| 东阿县| 塔河县| 平遥县| 临沂市| 新民市| 郓城县| 衡阳县| 枣庄市| 额敏县| 万安县| 武汉市| 福泉市| 会东县| 太谷县| 灌南县| 名山县| 抚松县| 怀安县|