Area--->AreaRegister.RegisterAllArea()与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 }
ReadTypesFromCache这个函数是先从缓存文件中找有没有缓存,一般情况是没有的。所以,我们直接略过(此段源代码也十分简单)。我们先看看FilterTypesInAssemblies代码,解析如下:
所有继承或实现AreaRegister的对象类都被找出来了,现在就是将这些对象序列化之后,写入MVC-AreaRegistrationTypeCache.xml文件里。我们接下来看看
三.CreateContextAndRegister解析:
CreateContextAndRegister对过滤后的对象实例化,并调用RegisterArea函数进行注册。
看到这里,用过Area的都知道庐山真面目了,看下图就知道了。
下一篇文章我们就要好好讲讲AreaRegistrationContext.MapRoute函数了。
四.总结:
总体上说来,RegisterAllArea方法的第一步是查看缓存文件内是否存在并有缓存信息,如果没有,则查找寻找当前项目所有继承或实现了AreaRegistration的对象。将这些对象信息缓存进缓存文件内,并实例化这些对象调用AreaRegistrationContext.MapRoute进行路由注册。
源码下载链接