<output id="qn6qe"></output>

    1. <output id="qn6qe"><tt id="qn6qe"></tt></output>
    2. <strike id="qn6qe"></strike>

      亚洲 日本 欧洲 欧美 视频,日韩中文字幕有码av,一本一道av中文字幕无码,国产线播放免费人成视频播放,人妻少妇偷人无码视频,日夜啪啪一区二区三区,国产尤物精品自在拍视频首页,久热这里只有精品12

      ASP.NET MVC Controller激活系統(tǒng)詳解:默認(rèn)實現(xiàn)

      Controller激活系統(tǒng)最終通過注冊的ControllerFactory創(chuàng)建相應(yīng)的Conroller對象,如果沒有對ControllerFactory類型或者類型進(jìn)行顯式注冊(通過調(diào)用當(dāng)前ControllerBuilder的SetControllerFactory方法),默認(rèn)使用的是一個DefaultControllerFactory對象,我們現(xiàn)在就來討論實現(xiàn)在DefaultControllerFactory類型中的默認(rèn)Controller激活機(jī)制。

      目錄
      一、Controller類型的解析
          實例演示:創(chuàng)建一個自定義ControllerFactory模擬Controller默認(rèn)激活機(jī)制
      二、 Controller類型的緩存
      三、 Controller的釋放
      四、會話狀態(tài)行為的控制

      一、Controller類型的解析

      激活目標(biāo)Controller對象的前提是能夠正確解析出對應(yīng)的Controller類型。對于DefaultControllerFactory來,用于解析目標(biāo)Controller類型的信息包括:通過與當(dāng)前請求匹配的路由對象生成的RouteData(其中包含Controller的名稱和命名空間)和包含在當(dāng)前ControllerBuilder中的命名空間。很對讀者可以首先想到的是通過Controller名稱得到對應(yīng)的類型,并通過命名空間組成Controller類型的全名,最后遍歷所有程序集以此名稱去加載相應(yīng)的類型即可。

      這貌似一個不錯的解決方案,實際上則完全不可行。不要忘了作為請求地址URL一部分的Controller名稱是不區(qū)分大小寫的,而類型名稱則是區(qū)分大小的;不論是注冊路由時指定的命名空間還是當(dāng)前ControllerBuilder的默認(rèn)命名空間,有可能是包含統(tǒng)配符(*)。由于我們不能通過給定的Controller名稱和命名空間得到Controller的真實類型名稱,自然就不可能通過名稱去解析Controller的類型了。

      ASP.NET MVC的Controller激活系統(tǒng)反其道而行之。它先遍歷通過BuildManager的靜態(tài)方法GetReferencedAssemblies方法得到的編譯Web應(yīng)用所使用的程序集,通過反射得到所有實現(xiàn)了接口IController的類型,最后通過給定的Controller的名稱和命名空間作為匹配條件在這個預(yù)先獲取的類型列表中得到目標(biāo)Controller的類型。

      實例演示:創(chuàng)建一個自定義ControllerFactory模擬Controller默認(rèn)激活機(jī)制

      為了讓讀者對默認(rèn)采用的Controller激活機(jī)制,尤其是Controller類型的解析機(jī)制有一個深刻的認(rèn)識,我們通過一個自定義的ControllerFactory來模擬其中的實現(xiàn)。由于我們采用反射的方式來創(chuàng)建Controller對象,所以我們將該自定義ControllerFactory起名為ReflelctionControllerFactory。[源代碼從這里下載]

         1: public class ReflelctionControllerFactory : IControllerFactory
         2: {
         3:     //其他成員
         4:     private static List<Type> controllerTypes;
         5:     static ReflelctionControllerFactory()
         6:     {
         7:         controllerTypes = new List<Type>();
         8:         foreach (Assembly assembly in BuildManager.GetReferencedAssemblies())
         9:         {
        10:             controllerTypes.AddRange(assembly.GetTypes().Where(type => typeof(IController).IsAssignableFrom(type)));
        11:         }
        12:     }
        13:  
        14:     public IController CreateController(RequestContext requestContext, string controllerName)
        15:     {
        16:         Type controllerType = this.GetControllerType(requestContext.RouteData, controllerName);
        17:         if (null == controllerType)
        18:         {
        19:             throw new HttpException(404, "No controller found");
        20:         }
        21:         return (IController)Activator.CreateInstance(controllerType);
        22:     }
        23:  
        24:     private static bool IsNamespaceMatch(string requestedNamespace, string targetNamespace)
        25:     {
        26:         if (!requestedNamespace.EndsWith(".*", StringComparison.OrdinalIgnoreCase))
        27:         {
        28:             return string.Equals(requestedNamespace, targetNamespace, StringComparison.OrdinalIgnoreCase);
        29:         }
        30:         requestedNamespace = requestedNamespace.Substring(0, requestedNamespace.Length - ".*".Length);
        31:         if (!targetNamespace.StartsWith(requestedNamespace, StringComparison.OrdinalIgnoreCase))
        32:         {
        33:             return false;
        34:         }
        35:         return ((requestedNamespace.Length == targetNamespace.Length) || (targetNamespace[requestedNamespace.Length] == '.'));
        36:     }
        37:  
        38:    private Type GetControllerType(IEnumerable<string> namespaces, Type[] controllerTypes)
        39:     {
        40:         var types = (from type in controllerTypes
        41:                         where namespaces.Any(ns => IsNamespaceMatch(ns, type.Namespace))
        42:                         select type).ToArray();
        43:         switch (types.Length)
        44:         {
        45:             case 0: return null;
        46:             case 1: return types[0];
        47:             default: throw new InvalidOperationException("Multiple types were found that match the requested controller name.");
        48:         }
        49:     }
        50:  
        51:     protected virtual Type GetControllerType(RouteData routeData, string controllerName)
        52:     {
        53:         //省略實現(xiàn)
        54:     }
        55: }

      如上面的代碼片斷所示,ReflelctionControllerFactory具有一個靜態(tài)的controllerTypes字段由于保存所有Controller的類型。在靜態(tài)構(gòu)造函數(shù)中,我們調(diào)用BuildManager的GetReferencedAssemblies方法得到所有用于編譯Web應(yīng)用的程序集,并從中得到所有實現(xiàn)了IController接口的類型,這些類型全部被添加到通過靜態(tài)字段controllerTypes表示的類型列表。

      Controller類型的解析實現(xiàn)在受保護(hù)的GetControllerType方法中,在用于最終激活Controller對象的CreateController方法中,我們通過調(diào)用該方法得到與指定RequestContext和Controller名稱相匹配的Controller類型,最終通過調(diào)用Activator的靜態(tài)方法CreateInstance根據(jù)該類型創(chuàng)建相應(yīng)的Controller對象。如果不能找到匹配的Controller類型(GetControllerType方法返回Null),則拋出一個HTTP狀態(tài)為404的HttpException。

      ReflelctionControllerFactory中定義了兩個輔助方法,IsNamespaceMatch用于判斷Controller類型真正的命名空間是否與指定的命名空間(可能包含統(tǒng)配符)相匹配,在進(jìn)行字符比較過程中是忽略大小寫的。私有方法GetControllerType根據(jù)指定的命名空間列表和類型名稱匹配的類型數(shù)組得到一個完全匹配的Controller類型。如果得到多個匹配的類型,直接拋出InvalidOperation異常,并提示具有多個匹配的Controller類型;如果找不到匹配類型,則返回Null。

      在如下所示的用于解析Controller類型的GetControllerType方法中,我們從預(yù)先得到的所有Controller類型列表中篩選出類型名稱與傳入的Controller名稱相匹配的類型。我們首先通過路由對象的命名空間對 之前 得到的類型列表進(jìn)行進(jìn)一步篩選,如果能夠找到一個唯一的類型,則直接將其作為Controller的類型返回。為了確定是否采用后備命名空間對Controller類型進(jìn)行解析,我們從作為參數(shù)參數(shù)的RouteData對象的DataTokens中得到獲取一個Key為“UseNamespaceFallback”的元素,如果該元素存在并且值為False,則直接返回Null。

      如果RouteData的DataTokens中不存在這樣一個UseNamespaceFallback元素,或者它的值為True,則首先里當(dāng)前ControllerBuilder的默認(rèn)命名空間列表進(jìn)一步對Controller類型進(jìn)行解析,如果存在唯一的類型則直接當(dāng)作目標(biāo)Controller類型返回。如果通過兩組命名空間均不能得到一個匹配的ControllerType,并且只存在唯一一個與傳入的Controller名稱相匹配的類型,則直接將該類型作為目標(biāo)Controller返回。如果這樣的類型具有多個,則直接拋出InvalidOperationException異常。

         1: public class ReflelctionControllerFactory : IControllerFactory
         2: {
         3:     //其他成員
         4:     protected virtual Type GetControllerType (RouteData routeData, string controllerName)
         5:     {
         6:         //根據(jù)類型名稱篩選
         7:         var types = controllerTypes.Where(type => string.Compare(controllerName + "Controller", type.Name, true) == 0).ToArray();
         8:         if (types.Length == 0)
         9:         {
        10:             return null;
        11:         }
        12:  
        13:         //通過路由對象的命名空間進(jìn)行匹配
        14:         var namespaces = routeData.DataTokens["Namespaces"] as IEnumerable<string>;
        15:         namespaces = namespaces ?? new string[0];
        16:         Type contrllerType = this.GetControllerType(namespaces, types);
        17:         if (null != contrllerType)
        18:         {
        19:             return contrllerType;
        20:         }
        21:  
        22:         //是否允許采用后備命名空間
        23:         bool useNamespaceFallback = true;
        24:         if (null != routeData.DataTokens["UseNamespaceFallback"])
        25:         {
        26:             useNamespaceFallback = (bool)(routeData.DataTokens["UseNamespaceFallback"]);
        27:         }
        28:  
        29:         //如果不允許采用后備命名空間,返回Null
        30:         if (!useNamespaceFallback)
        31:         {
        32:             return null;
        33:         }
        34:  
        35:         //通過當(dāng)前ControllerBuilder的默認(rèn)命名空間進(jìn)行匹配
        36:         contrllerType = this.GetControllerType(ControllerBuilder.Current.DefaultNamespaces, types);
        37:         if (null != contrllerType)
        38:         {
        39:             return contrllerType;
        40:         }
        41:  
        42:         //如果只存在一個類型名稱匹配的Controller,則返回之
        43:         if (types.Length == 1)
        44:         {
        45:             return types[0];
        46:         }
        47:  
        48:         //如果具有多個類型名稱匹配的Controller,則拋出異常
        49:         throw new InvalidOperationException("Multiple types were found that match the requested controller name.");
        50:     }
        51: }

      二、 Controller類型的緩存

      為了避免通過遍歷所有程序集對目標(biāo)Controller類型的解析,ASP.NET MVC對解析出來的Controller類型進(jìn)行了緩存以提升性能。與針對用于Area注冊的AreaRegistration類型的緩存類似,Controller激活系統(tǒng)同樣采用基于文件的緩存策略,而用于保存Controller類型列表的名為MVC-ControllerTypeCache.xml的文件保存在ASP.NET的臨時目錄下面。具體的路徑如下,其中第一個針對寄宿于IIS中的Web應(yīng)用,后者針對直接通過Visual Studio Developer Server作為宿主的應(yīng)用。而用于保存所有AreaRegistration類型列表的MVC-AreaRegistrationTypeCache.xml文件也保存在這個目錄下面。

      • %Windir%\Microsoft.NET\Framework\v{version}\Temporary ASP.NET Files\{appname}\...\...\UserCache\
      • %Windir%\Microsoft.NET\Framework\v{version}\Temporary ASP.NET Files\root\...\...\UserCache\

      對針對Web應(yīng)用被啟動后的第一個請求時,Controller激活系統(tǒng)會讀取這個用于緩存所有Controller類型列表的ControllerTypeCache.xml文件并反序列化成一個List<Type>對象。只有在該列表為空的時候才會通過遍歷程序集和反射的方式得到所有實現(xiàn)了接口IController的公有類型,而被解析出來的Controller類型重寫被寫入ControllerTypeCache.xml文件中。這個通過讀取緩存文件或者重新解析出來的Controller類型列表被保存到內(nèi)容中,在Web應(yīng)用活動期間內(nèi)被Controller激活系統(tǒng)所用。

      下面的XML片斷反映了這個用于Controller類型列表緩存的ControllerTypeCache.xml文件的結(jié)構(gòu),我們可以看出它包含了所有的Controller類型的全名和所在的程序集和托管模塊信息。

         1: <?xml version="1.0" encoding="utf-8"?>
         2: <!--This file is automatically generated. Please do not modify the contents of this file.-->
         3: <typeCache lastModified="3/22/2012 1:18:49 PM" mvcVersionId="80365b23-7a1d-42b2-9e7d-cc6f5694c6d1">
         4:   <assembly name="Artech.Admin, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null">
         5:     <module versionId="eb343e3f-2d63-4665-a12a-29fb30dceeed">
         6:       <type> Artech.Admin .HomeController</type>
         7:       <type> Artech.Admin .EmployeeController </type>
         8:     </module>
         9:   </assembly>
        10:   <assembly name="Artech.Portal, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null">
        11:     <module versionId=" 3717F116-35EE-425F-A1AE-EB4267497D8C ">
        12:       <type>Artech. Portal.Controllers.HomeController</type>
        13:       <type>Artech. Portal.ProductsController</type>
        14:     </module>
        15:   </assembly>
        16: </typeCache>

      三、 Controller的釋放

      作為激活Controller對象的ControllerFactory不僅僅用于創(chuàng)建目標(biāo)Controller對象,還具有兩個額外的功能,即通過ReleaseController方法對激活的Controller對象進(jìn)行釋放和回收,以及通過GetControllerSessionBehavior返回用于控制當(dāng)前會話狀態(tài)行為的SessionStateBehavior枚舉。

      對于默認(rèn)使用DefaultControllerFactory來說,針對Controller對象的釋放操作很簡單:如果Controller類型實現(xiàn)了IDisposable接口,則直接調(diào)用其Dispose方法即可;否則直接忽略。我們將這個邏輯也實現(xiàn)在了我們自定義的ReflelctionControllerFactory中。

         1: public class ReflelctionControllerFactory : IControllerFactory
         2: {
         3:     //其他操作
         4:     public void ReleaseController(IController controller)
         5:     {
         6:         IDisposable disposable = controller as IDisposable;
         7:         if (null != disposable)
         8:         {
         9:             disposable.Dispose();
        10:         }
        11:     }
        12: }

      四、會話狀態(tài)行為的控制

      至于用于返回SessionStateBehavior枚舉的GetControllerSessionBehavior方法來說,在默認(rèn)的情況下的返回值為SessionStateBehavior.Default。通過前面的介紹我們知道在這種情況下具體的會話狀態(tài)行為取決于創(chuàng)建的HttpHandler所實現(xiàn)的標(biāo)記接口。對于ASP.NET MVC應(yīng)用來說,默認(rèn)用于處理請求的HttpHandler是一個叫做MvcHandler的對象,如下面的代碼片斷所示,HttpHandler實現(xiàn)了IRequiresSessionState接口,意味著默認(rèn)情況下會話狀態(tài)是可讀寫的(相當(dāng)于SessionStateBehavior.Requried)。

         1: public class MvcHandler : 
         2: IHttpAsyncHandler, 
         3: IHttpHandler, 
         4: IRequiresSessionState
         5: {
         6:     //其他成員
         7: }

      不過我們可以通過在Controller類型上應(yīng)用SessionStateAttribute特性來具體控制會話狀態(tài)行為。如下面的代碼片斷所示,SessionStateAttribute具有一個SessionStateBehavior類型的只讀屬性Behavior用于返回具體行為設(shè)置的會話狀態(tài)行為選項,該屬性是在構(gòu)造函數(shù)中被初始化的。

         1: [AttributeUsage(AttributeTargets.Class, AllowMultiple = false, Inherited = true)]
         2: public sealed class SessionStateAttribute : Attribute
         3: {
         4:     public SessionStateAttribute(SessionStateBehavior behavior);
         5:     public SessionStateBehavior Behavior { get; }
         6: }

      也就是說DefaultControllerFactory會通過解析出來的Controller類型得到應(yīng)用在上面的SessionStateAttribute特性,如果這樣的特性存在則直接返回它的Behavior屬性所表示的SessionStateBehavior枚舉;如果不存在則返回SessionStateBehavior.Default,具體的邏輯反映在我們自定義的ReflelctionControllerFactory的GetControllerSessionBehavior方法中。

         1: public class ReflelctionControllerFactory : IControllerFactory
         2: {
         3:     //其他成員
         4:     public SessionStateBehavior GetControllerSessionBehavior(RequestContext requestContext, string controllerName)
         5:     {
         6:         Type controllerType = this.GetControllerType(requestContext.RouteData, controllerName);
         7:         if (null == controllerType)
         8:         {
         9:             return SessionStateBehavior.Default;
        10:         }
        11:         SessionStateAttribute attribute = controllerType.GetCustomAttributes(true).OfType<SessionStateAttribute>()
        12:            .FirstOrDefault();
        13:         attribute = attribute ?? new SessionStateAttribute(SessionStateBehavior.Default);
        14:         return attribute.Behavior;
        15:     }    
        16: }
      ASP.NET MVC Controller激活系統(tǒng)詳解:總體設(shè)計
      ASP.NET MVC Controller激活系統(tǒng)詳解:默認(rèn)實現(xiàn)
      ASP.NET MVC Controller激活系統(tǒng)詳解:IoC的應(yīng)用[上篇]
      ASP.NET MVC Controller激活系統(tǒng)詳解:IoC的應(yīng)用[下篇]
      posted @ 2012-03-31 12:54  Artech  閱讀(8310)  評論(9)    收藏  舉報
      主站蜘蛛池模板: 国产日韩久久免费影院| 亚洲日韩日本中文在线| 麻豆蜜桃av蜜臀av色欲av| 色婷婷日日躁夜夜躁| 日韩一区二区三区无码影院| 4399理论片午午伦夜理片| 国产不卡一区二区精品| 广州市| 亚洲日韩成人无码不卡网站| 无码日韩精品91超碰| 亚洲人妻精品一区二区| 日本狂喷奶水在线播放212| 国产日韩欧美亚洲精品95| 亚洲人成网线在线播放VA| 亚洲av成人无网码天堂| 男人狂桶女人出白浆免费视频| 日韩av日韩av在线| 免费看欧美全黄成人片| 日韩国产精品中文字幕| 欧美乱码卡一卡二卡四卡免费| 久久天天躁夜夜躁狠狠820175| 日本高清在线播放一区二区三区| 亚洲国产精品日韩专区av| 成人午夜福利视频后入| 国产午夜福利不卡在线观看| 精品国产成人国产在线观看| 国产午夜亚洲精品国产成人| 激情伊人五月天久久综合| 69精品丰满人妻无码视频a片| 日韩秘 无码一区二区三区| 国产精品亚洲二区在线看| 国产成人亚洲日韩欧美| 人妻久久久一区二区三区| 公天天吃我奶躁我的在| 亚洲国产精品久久久天堂麻豆宅男 | 99精品人妻少妇一区二区| 国产亚洲精品第一综合另类无码无遮挡又大又爽又黄的视频 | www插插插无码免费视频网站| 日韩亚av无码一区二区三区 | 男人扒开女人内裤强吻桶进去| 成人午夜大片免费看爽爽爽|