码迷,mamicode.com
首页 > 其他好文 > 详细

区域路由的注册机制

时间:2017-07-01 22:39:13      阅读:344      评论:0      收藏:0      [点我收藏+]

标签:document   f11   mina   一个   构造器   继承   输出   enum   soft   

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没有命名空间,那就允许它退回(到其他地方找)。

原文来自:技术之家

区域路由的注册机制

标签:document   f11   mina   一个   构造器   继承   输出   enum   soft   

原文地址:http://www.cnblogs.com/buntinginfo/p/7103515.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!