Area--->AreaRegister.RegisterAllArea()与Area区域的解析

文章引导

              MVC路由解析---IgnoreRoute 

              MVC路由解析---MapRoute 

              MVC路由解析---UrlRoutingModule  

              Area的使用

              Area--->AreaRegister.RegisterAllArea()与Area区域的解析

引言:

               学习本文建议先看下另一篇文章(Area的使用),此篇文章着重解析AreaRegister.RegisterAllArea()与Area的关联性。

       一.从AreaRegistration.RegiatrationAllArea说起:

               MVC的Application_Start函数的第一句代码就是AreaRegistration.RegisterAlllArea()。我们今天要讲的内容也是仿真.NET的AreaRegistration.RegisterAllArea()来说起。我们先来讲讲RegisterAllArea的执行过程。

               第一步:                          

        public static void RegisterAllAreas()
        {
            RegisterAllAreas(null);
        }
        public static void RegisterAllAreas(object state)
        {
            RegisterAllAreas(RouteTable.Routes, new BuildManagerWrapper(), state);
        }
        public static void RegisterAllAreas(RouteCollection routes,IBuildManager builder,object state)
        {
            using (List<Type>.Enumerator enumator = TypeCacheUtil.GetFilteredTypesFromAssemblies("MVC-AreaRegistrationTypeCache.xml",
                                                                                               new Predicate<Type>(AreaRegistration.IsAreaRegistrationType),
                                                                                               builder
                ).GetEnumerator())
            {
                while(enumator.MoveNext())
                {
                    ((AreaRegistration)Activator.CreateInstance(enumator.Current)).CreateContextAndRegister(routes, state);
                }
            }
        }

 

               可以看的到,程序先进入RegisterAllArea(),然后通过赋予参数null,来执行RegisterAllArea(null)从而来执行接下来的同名函数RegisterAlllArea(object state)。这里还没有完,接着继续进行RegisterAllArea(RouteTable.Routes,new BuildManagerWrapper(),state)。这里的RouteTable是一个RouteCollection的单例对象,具体内容可以看我的此系列的相关文章。

               走到这一步我们看到进入到真正的执行内容了,接着解析下图

                              

               上图的函数的意义:先从UserCache缓存文件夹找寻是否存在对应的xml缓存文件。如果不存在,则将所有继承AreaRegister的类,将其都进行实例化、生成对象、并调用RegisterArea(AreaRegistrationContext)进行路由注册。

       二.GetFilteredTypesFromAssemblies解析:

                上面总体说了关于此函数的意义,接下来我们来深入解剖代码:

 1 public static List<Type> GetFilteredTypesFromAssemblies(string cacheName,Predicate<Type> predicate,IBuildManager buildManager)
 2         {
 3             TypeCacheSerializer serializer = new TypeCacheSerializer();
 4             List<Type> matchingTypes = ReadTypesFromCache(cacheName, predicate, buildManager, serializer);
 5             if(matchingTypes==null)
 6             {
 7                 matchingTypes = FilterTypesInAssemblies(buildManager, predicate).ToList<Type>();
 8                 SaveTypesToCache(cacheName, matchingTypes, buildManager, serializer);
 9             }
10             return matchingTypes;
11 
12         }
13         private static IEnumerable<Type> FilterTypesInAssemblies(IBuildManager buildManager, Predicate<Type> predicate)
14         {
15             IEnumerable<Type> emptyTypes = Type.EmptyTypes;
16             foreach (Assembly assembly in buildManager.GetReferencedAssemblies())
17             {
18                 Type[] types;
19                 try
20                 {
21                     types = assembly.GetTypes();
22                 }
23                 catch (ReflectionTypeLoadException exception1)
24                 {
25                     types = exception1.Types;
26                 }
27                 emptyTypes = emptyTypes.Concat<Type>(types);
28             }
29             return (from type in emptyTypes
30                     where TypeIsPublicClass(type) && predicate(type)
31                     select type);
32         }
33         internal static void SaveTypesToCache(string cacheName, IList<Type> matchingTypes, IBuildManager buildManager, TypeCacheSerializer serializer)
34         {
35             try
36             {
37                 Stream stream = buildManager.CreateCachedFile(cacheName);
38                 if (stream != null)
39                 {
40                     using (StreamWriter writer = new StreamWriter(stream))
41                     {
42                         serializer.SerializeTypes(matchingTypes, writer);
43                     }
44                 }
45             }
46             catch
47             {
48             }
49         }
View Code

                ReadTypesFromCache这个函数是先从缓存文件中找有没有缓存,一般情况是没有的。所以,我们直接略过(此段源代码也十分简单)。我们先看看FilterTypesInAssemblies代码,解析如下:

                             

                所有继承或实现AreaRegister的对象类都被找出来了,现在就是将这些对象序列化之后,写入MVC-AreaRegistrationTypeCache.xml文件里。我们接下来看看

                               

      三.CreateContextAndRegister解析:

                CreateContextAndRegister对过滤后的对象实例化,并调用RegisterArea函数进行注册。

                

                看到这里,用过Area的都知道庐山真面目了,看下图就知道了。

               

               下一篇文章我们就要好好讲讲AreaRegistrationContext.MapRoute函数了。

       四.总结:

               总体上说来,RegisterAllArea方法的第一步是查看缓存文件内是否存在并有缓存信息,如果没有,则查找寻找当前项目所有继承或实现了AreaRegistration的对象。将这些对象信息缓存进缓存文件内,并实例化这些对象调用AreaRegistrationContext.MapRoute进行路由注册。

       源码下载链接

 

 

               

posted @ 2018-10-15 20:09  小王子的博客  阅读(1121)  评论(0编辑  收藏  举报