區域路由的注冊機制

AreaRegistration.RegisterAllAreas()

?我們新建一個名稱為Admin的Area,VS生成下面的代碼。

復制代碼

???????{?action?=?,?id?=

復制代碼

我們先來看AreaRegistration這個抽象類,實際上,它只有一個核心功能,就是RegisterAllAreas,獲取所有繼承它的子類類型,然后創建它,在為他創建一個AreaRegistrationContext,在調用它的RegisterArea方法。

復制代碼

?????TypeCacheName?=????AreaName?{????RegisterAllAreas(RouteCollection?routes,?IBuildManager?buildManager,?<Type>?areaRegistrationTypes?=?(Type?areaRegistrationType?=??CreateContextAndRegister(RouteCollection?routes,?=??thisNamespace?=?(thisNamespace?!=?+

復制代碼

為什么要有AreaRegistrationContext這個類型呢?假如沒有它,AreaRegistration子類創建完成時,就可以直接注冊了,我們的AdminAreaRegistration的RegisterArea方法完全可以通過RouteCollection再重載一個MapRoute方法用于Area路由的注冊。像下面這個樣子。

復制代碼

???{?action?=?,?id?=

復制代碼

?這樣不是很好么?跟隨著源碼,詳細瞧一瞧這個AreaRegistrationContext

AreaRegistrationContext

?這個類本質上只有一個屬性,那就是命名空間。

復制代碼

???HashSet<>?_namespaces?=??HashSet<>?AreaRegistrationContext(?areaName,?RouteCollection?routes,???AreaName?{?;???ICollection<>?{??RouteCollection?Routes?{?;????State?{?;???Route?MapRoute(?name,??url,??defaults,??constraints,

復制代碼

?我們回到核心的RegisterAllAreas方法中。

復制代碼

??(AreaRegistration).IsAssignableFrom(type)?&&!=????RegisterAllAreas(RouteCollection?routes,?IBuildManager?buildManager,?<Type>?areaRegistrationTypes?=?(Type?areaRegistrationType?=

復制代碼

通過TypeCacheUtil.GetFilteredTypesFromAssemblies獲取出來的類型必須符合IsAreaRegistrationType委托,(AreaRegistration).IsAssignableFrom(type)不難理解,必須是AreaRegistration的子類,那type.GetConstructor(Type.EmptyTypes)呢?其實一開始我也不明白它是什么意思,后來通過Console寫了個小程序測試了下。

??Main(=??tac?==??tbc?==??tcc?=?+?(tac?!=??+?(tbc?!=??+?(tcc?!=

View Code

?輸出:

類TA?:False

類TB?:False

類TC?:True

請按任意鍵繼續.?.?.

我們可以明白了,也就是我們的AdminAreaRegistration不能有構造器(Visual Studio生成的確實沒有構造器)。但是這里為什么要這樣約定呢?確實想不通,我們先繼續回到剛剛的TypeCacheUtil.GetFilteredTypesFromAssemblies方法。首先,會嘗試從緩存中獲取類型,與往常不同的是,這里緩存的格式是xml文件,緩存的原因應該很容易理解,頻繁反射會造成性能的影響,改良反射的方式有多種,這里我們學到了一種,緩存。關于TypeCacheSerializer如何工作和ReadTypesFromCache具體是如何實現的這里就不去看了,主要就是一些關于Stream和XmlDocument這兩個類的操作。但是有必要提一下IBuildManager這個接口。在MVC中的實現者是BuildManagerWrapper,內部實際使用的是BuildManager(位于System.Web.Compilation),關于它的詳細資料少之又少,只知道主要負責站點的動態編譯和程序集的管理。我們知道可以通過AppDomain來獲取應用程序相關的程序集,但這里為什么用BuilderManager呢?想必必有什么不同!

復制代碼

??IEnumerable<Type>?FilterTypesInAssemblies(IBuildManager?buildManager,?Predicate<Type>IEnumerable<Type>?typesSoFar?==?(Assembly?assembly?===?typesSoFar.Where(type?=>?TypeIsPublicClass(type)?&&

復制代碼

我們看到這里用它獲取所有的應用程序集。在foreach前打一個斷點。借助即時窗口我們可以和AppDomain獲取的程序集進行一個比較。

string[]?Arr1?=?assemblies.Cast().Select(a=>a.FullName).ToArray();

已計算表達式,表達式沒有值

string[]?Arr2?=?AppDomain.CurrentDomain.GetAssemblies().Select(a=>a.FullName).ToArray();

已計算表達式,表達式沒有值

Arr1.Length

36

Arr2.Length

42

string[]?Arr3?=?Arr2.Except(Arr1).ToArray();

已計算表達式,表達式沒有值

Arr3

{string[6]}

????[0]:?"System.Runtime.Caching,?Version=4.0.0.0,?Culture=neutral,?PublicKeyToken=b03f5f7f11d50a3a"

????[1]:?"Microsoft.Build.Utilities.v4.0,?Version=4.0.0.0,?Culture=neutral,?PublicKeyToken=b03f5f7f11d50a3a"

????[2]:?"Microsoft.JScript,?Version=10.0.0.0,?Culture=neutral,?PublicKeyToken=b03f5f7f11d50a3a"

????[3]:?"Microsoft.VisualStudio.Web.PageInspector.Runtime,?Version=15.0.0.0,?Culture=neutral,?PublicKeyToken=b03f5f7f11d50a3a"

????[4]:?"Microsoft.VisualStudio.Web.PageInspector.Tracing,?Version=15.0.0.0,?Culture=neutral,?PublicKeyToken=b03f5f7f11d50a3a"

? ? [5]:?"Microsoft.VisualStudio.Debugger.Runtime,?Version=15.0.0.0,?Culture=neutral,?PublicKeyToken=b03f5f7f11d50a3a"

這里列出的幾個命名空間我也不熟悉,但是大致可以了解,使用AppDomain返回的程序集是當前AppDomain下所有程序中顯示使用過的類型所在的程序集(如果你對AppDomain有了解,希望不要被我誤解),而BuildManager返回的是和程序運行環境甚至配置(調試)相關的程序集,我們可以這么理解,BuildManager提供更強大的功能,可以負責站點的動態編譯和程序集的管理。關于AreaRegistration類型的緩存我們基本已經了解,拿到所有的AreaRegistration類型后,我們針對每一個進行一次路由配置工作。

復制代碼

???RegisterAllAreas(RouteCollection?routes,?IBuildManager?buildManager,?<Type>?areaRegistrationTypes?=?(Type?areaRegistrationType?=

復制代碼

具體的

復制代碼

??CreateContextAndRegister(RouteCollection?routes,?=??thisNamespace?=?(thisNamespace?!=?+

復制代碼

我們來思考一下,這個thisNamespace會是什么值呢?由于這里的GetType目標是AdminAreaRegistration,(在我這里)所以是Mvc_Web.Areas.Admin,然后會被添加到這里的AreaRegistrationContext的Namespace屬性中,然后調用子類重寫的RegisterArea方法,最終添加到RouteCollection中,我們看最后調用的MapRoute方法。

復制代碼

?Route?MapRoute(?name,??url,??defaults,??constraints,??(namespaces?==??&&?Namespaces?!=?===?useNamespaceFallback?=?(namespaces?==??||?namespaces.Length?==?=

復制代碼

最重要的是倒數第二行和倒數第三行,他和控制器的匹配有關,其實根據UseNamespaceFallback這個也很容易理解,如果我們的AdminAreaRegistration沒有命名空間,那就允許它退回(到其他地方找)。

原文來自:技術之家

轉載于:https://www.cnblogs.com/buntinginfo/p/7103515.html

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/254166.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/254166.shtml
英文地址,請注明出處:http://en.pswp.cn/news/254166.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

Unix/Linux IPC及線程間通信總結

一、互斥與同步 1.互斥&#xff1a;是指某一資源同時只允許一個訪問者對其進行訪問&#xff0c;具有唯一性和排它性。但互斥無法限制訪問者對資源的訪問順序&#xff0c;即訪問是無序的。 2.同步&#xff1a;是指在互斥的基礎上&#xff08;大多數情況&#xff09;&#xff0…

CSS樣式的插入方式

1.外部樣式&#xff1a; 當樣式需要應用于很多頁面時&#xff0c;外部樣式表將是理想的選擇。<head><link rel"stylesheet" type"text/css" href"mystyle.css" /> </head> 2.內部樣式 當單個文檔需要特殊的樣式時&#…

嵌入式Linux系統基礎知識

一、嵌入式Linux系統的構成 1、硬件 2、內核 3、應用程序&#xff08;形成根文件系統&#xff09; 二、構建嵌入式Linux系統的主要任務 1、內核部分 2、應用程序部分 嵌入式Linux的開發大致可分為三個層次&#xff1a;引導裝載內核、構造文件系統和圖形用戶界面。作為操作系統…

win10系統javac不是內部或外部命令,也不是可運行的程序 或批處理文件。

按照下面的步驟設置環境變量 說明&#xff1a; 1. 如果編輯的是系統環境變量&#xff0c;命令提示符需要以管理員權限運行&#xff1b;如果在用戶環境變量中編輯&#xff0c;則當前用可直接運行命令提示符。 2. win10中的路徑相對于win7要設置成絕對路徑。 1&#xff0e;打開…

兩個bat文件

1、修改后綴名 ren *.cs *.txt ren *.txt *.zip2、修改文件名稱 echo offset a00setlocal EnableDelayedExpansionfor %%n in (*.txt) do (set /A a1ren "%%n" "!a!.txt")

各種排序筆記---基于比較排序部分

1. 選擇排序 selection sort 大循環 從左到右每次以一個點開始掃描array 小循環 找到從當前起始點開始的最小值 時間復雜度為O(N^2) //selection sort an array array[] public class Solution {public int[] solve(int[] array) {if (array null || array.length 0) {return…

是什么讓深度學習再次崛起并超越人類?

作者潘爭&#xff0c;格靈深瞳計算機視覺工程師&#xff0c;清華大學自動化系博士&#xff0c;師從智能技術與系統國家重點實驗室副主任張長水。深度學習(Deep Learning)這個詞最近借著AlphaGO與李世石的人機大戰又火了一把。深度學習其實是機器學習(Machine Learning)的一個分…

常見的流量問題

常見的流量問題 冗余內容同類請求被間隔執行&#xff0c;請求的內容包含一些相對靜態的信息&#xff0c;正確的處理是第一次請求包括靜態信息就好&#xff0c;后面的同類請求只包含必要的即時變化信息即可。錯誤的處理方式是每次請求服務器都返回一次靜態信息。 冗余請求有的時…

halcon使用點擬合圓形時候,點集順序紊亂,不影響圓形擬合效果

read_image (Image, 截圖20201226094342972.bmp) * Matching 01: BEGIN of generated code for model initialization set_system (border_shape_models, false) * Matching 01: Obtain the model image * Matching 01: The image is assumed to be made available in the * Ma…

Socket理解。

其他大部分系統&#xff0c;例如CRM/CMS/權限框架/MIS之類的&#xff0c;無論怎么復雜&#xff0c;基本上都能夠本地代碼本地調試&#xff0c;性能也不太重要。&#xff08;也許這個就是.net的企業級開發的戰略吧&#xff09; 可是來到通訊系統&#xff0c;一切變得困難復雜。原…

多元化時代敏捷軟件開發的崛起與傳統軟件工程的延續

多元化時代敏捷軟件開發的崛起與傳統軟件工程的延續 1.傳統軟件開發模式 1.1瀑布模型 1.1.1概念 瀑布模型&#xff0c;顧名思義&#xff0c;軟件開發的過程如同瀑布飛流一般&#xff0c;自上而下&#xff0c;逐級下落。瀑布模型的核心思想是將問題按照工序進行簡化&#xff0c;…

Linux中的cron計劃任務配置詳解

cron來源于希臘單詞chronos&#xff08;意為“時間”&#xff09;&#xff0c;指Linux系統下一個自動執行指定任務的程序&#xff08;計劃任務&#xff09; ####1. crontab命令選項代碼如下: #crontab -u <-l, -r, -e> -u指定一個用戶 -l列出某個用戶的任務計劃 -r刪除某…

new和delete

和 sizeof 類似&#xff0c;sizeof不是函數&#xff0c;它是一個操作符&#xff0c;它在編譯期就完成了計算&#xff0c;在函數運行期間它已經是一個常數值了。 int a;sizeof(int) 4;sizeof(a) 4;sizeof a ——也是4 不需要括號&#xff01;此時要注意&#xff1a;sizeof in…

char a[]和char *a的比較,數組名,數組首地址,a,a,a[0]

char a[]和char *a的比較 指針和數組存在著一些本質的區別。當然&#xff0c;在某種情況下&#xff0c;比如數組作為函數的參數進行傳遞時&#xff0c;由于該數組自動退化為同類型的指針&#xff0c;所以在函數內部&#xff0c;作為函數參數傳遞進來的指針與數組確實具有一定的…

Java中繼承thread類與實現Runnable接口的區別

Java中線程的創建有兩種方式&#xff1a; 1&#xff0e; 通過繼承Thread類&#xff0c;重寫Thread的run()方法&#xff0c;將線程運行的邏輯放在其中 2&#xff0e; 通過實現Runnable接口&#xff0c;實例化Thread類 在實際應用中&#xff0c;我們經常用到多線程&#xff0c;…

【VMware vSAN 6.6】6.2.啟用性能服務:vSAN硬件服務器解決方案

目錄 1. 簡介 1.1.適用于HCI的企業級存儲2. 體系結構 2.1.帶有本地存儲的服務器2.2.存儲控制器虛擬系統套裝的缺點2.3.vSAN在vSphere Hypervisor中自帶2.4.集群類型2.5.硬件部署選項3. 啟用vSAN 3.1.啟用vSAN3.2.輕松安裝3.3.主動測試4. 可用性 4.1.對象和組件安置4.2.重新構建…

Android eclipse導入項目后出現Unable to resolve target #39;android-17#39;解決方法

eclipse導入項目后出現Unable to resolve target android-17解決方法。在最后附帶還有一種編譯邏輯不成功情況解決方法。 一、問題情況 二、解決的方法 1、改動項目的目標版本號與當前Android sdk相相應的版本號 2、自己主動修復一下項目 三、這個問題不是上面的。是另外情況&a…

多個圓點,鼠標選取兩個,求兩個點的距離,用于計算像素尺寸(halcon實現)

read_image (Image, C:/Users/22967/Desktop/晶圓找位置/0.bmp) dev_close_window () dev_open_window_fit_image (Image, 0, 0, -1, -1, WindowHandle) dev_display (Image)binary_threshold (Image, Region1, max_separability, dark, UsedThreshold) connection (Region1, C…

修改UBOOT和LINUX調試串口(TI達芬奇芯片--DM6467)

Posted on 2011-10-31 10:53 jamiedu 閱讀(889) 評論(0) 編輯 收藏 1.1 概述 TI針對DM6467提供的UBOOT和內核默認都是串口0作為調試串口輸出的&#xff0c;但現在我需要使用DM6467的UART0的modem功能&#xff0c;所以修改代碼&#xff0c;改變調試串口為串口2。 需要修改的主要…

Java List與數組之間的轉換

http://blog.csdn.net/kingzone_2008/article/details/8444678轉載于:https://www.cnblogs.com/longshiyVip/p/5985981.html