在MVC中注册Area时,我们一般会在相应的区域下定义一个继承与AreaRegistration的类,代码如下:

public class AdminAreaRegistration : AreaRegistration
{
public override string AreaName
{
get
{
return "Admin";
}
} public override void RegisterArea(AreaRegistrationContext context)
{
context.MapRoute(
"Admin_default",
"Admin/{controller}/{action}/{id}",
new { action = "Index", id = UrlParameter.Optional }
);
}
}

那么问题来了,类AdminAreaRegistration是在什么时候被实例化的,方法RegisterArea是何时被调用的?

1、Global中注册所有区域

AreaRegistration.RegisterAllAreas();

2、查看AreaRegistration.RegisterAllAreas源码

internal static void RegisterAllAreas(RouteCollection routes, IBuildManager buildManager, object state)
{
//从缓存以及组件中查找所有的AreaRegistration
List<Type> filteredTypesFromAssemblies = TypeCacheUtil.GetFilteredTypesFromAssemblies("MVC-AreaRegistrationTypeCache.xml", new Predicate<Type>(AreaRegistration.IsAreaRegistrationType), buildManager);
foreach (Type current in filteredTypesFromAssemblies)
{
AreaRegistration areaRegistration = (AreaRegistration)Activator.CreateInstance(current); areaRegistration.CreateContextAndRegister(routes, state);
}
}

3、从缓存及引用程序集中查找Type

public static List<Type> GetFilteredTypesFromAssemblies(string cacheName, Predicate<Type> predicate, IBuildManager buildManager)
{
TypeCacheSerializer serializer = new TypeCacheSerializer();
//从缓存中查找AreaRegistration
List<Type> list = TypeCacheUtil.ReadTypesFromCache(cacheName, predicate, buildManager, serializer);
if (list != null)
{
return list;
}
//从组件中查找AreaRegistration
list = TypeCacheUtil.FilterTypesInAssemblies(buildManager, predicate).ToList<Type>();
//添加缓存
TypeCacheUtil.SaveTypesToCache(cacheName, list, buildManager, serializer);
return list;
}

4、从程序集中查找Type

private static IEnumerable<Type> FilterTypesInAssemblies(IBuildManager buildManager, Predicate<Type> predicate)
{
IEnumerable<Type> enumerable = Type.EmptyTypes;
//获取所有被引用的组件
ICollection referencedAssemblies = buildManager.GetReferencedAssemblies();
foreach (Assembly assembly in referencedAssemblies)
{
Type[] types;
try
{
//获取组件中的所有类型
types = assembly.GetTypes();
}
catch (ReflectionTypeLoadException ex)
{
types = ex.Types;
} enumerable = enumerable.Concat(types);
} //返回所有类型中的AreaRegistration
return from type in enumerable
where TypeCacheUtil.TypeIsPublicClass(type) && predicate(type)
select type;
}

5、此处使用predicate(type),不得不回到步骤2看看传入的是啥

private static bool IsAreaRegistrationType(Type type)
{
return typeof(AreaRegistration).IsAssignableFrom(type) && type.GetConstructor(Type.EmptyTypes) != null;
}

6、此时已找到所有的AreaRegistration类,再次回到步骤2,创建AreaRegistration实例,并调用方法RegisterArea

internal void CreateContextAndRegister(RouteCollection routes, object state)
{
AreaRegistrationContext areaRegistrationContext = new AreaRegistrationContext(this.AreaName, routes, state);
string @namespace = base.GetType().Namespace;
if (@namespace != null)
{
areaRegistrationContext.Namespaces.Add(@namespace + ".*");
}
this.RegisterArea(areaRegistrationContext);
}

由以上代码可以看书,方法RegisterAllAreas就是简单粗暴的将所有引用程序集中的类型遍历一遍,找到所有的AreaRegistration,并调用注册区域方法。

为了验证以上观点,特做了以下测试。

新建一个类库程序,并在类库程序中注册区域,观察是否注册成功。文件结构如下

测试结果:

由于本人也是最近才接触MVC,在学习过程中碰到一些问题,特此备注

1、Mvc定义区域外层文件夹约定为Areas
2、Views文件夹下一定要有web.config,否则会报错(当前上下文中不存在名称“ViewBag”),可以复制项目Views下自动生成的Web.config
3、注册区域可以在其他被引用的项目中(AreaRegistration)

探索RegisterAllAreas的更多相关文章

  1. .net EntityFramework用法探索系列 1

    EntityFramework用法探索系列 (一)DatabaseFirst (二)CodeFirst (三)CodeFirst流畅API (四)Repository和UnitOfWork (五)引入 ...

  2. 【探索】机器指令翻译成 JavaScript

    前言 前些时候研究脚本混淆时,打算先学一些「程序流程」相关的概念.为了不因太枯燥而放弃,决定想一个有趣的案例,可以边探索边学. 于是想了一个话题:尝试将机器指令 1:1 翻译 成 JavaScript ...

  3. 【探索】利用 canvas 实现数据压缩

    前言 HTTP 支持 GZip 压缩,可节省不少传输资源.但遗憾的是,只有下载才有,上传并不支持.如果上传也能压缩,那就完美了.特别适合大量文本提交的场合,比如博客园,就是很好的例子. 虽然标准不支持 ...

  4. 探索C#之6.0语法糖剖析

    阅读目录: 自动属性默认初始化 自动只读属性默认初始化 表达式为主体的函数 表达式为主体的属性(赋值) 静态类导入 Null条件运算符 字符串格式化 索引初始化 异常过滤器when catch和fin ...

  5. Mysql事务探索及其在Django中的实践(二)

    继上一篇<Mysql事务探索及其在Django中的实践(一)>交代完问题的背景和Mysql事务基础后,这一篇主要想介绍一下事务在Django中的使用以及实际应用给我们带来的效率提升. 首先 ...

  6. Linux学习之探索文件系统

    Linux,一起学习进步-    ls With it, we can see directory contents and determine a variety of important file ...

  7. 马里奥AI实现方式探索 ——神经网络+增强学习

    [TOC] 马里奥AI实现方式探索 --神经网络+增强学习 儿时我们都曾有过一个经典游戏的体验,就是马里奥(顶蘑菇^v^),这次里约奥运会闭幕式,日本作为2020年东京奥运会的东道主,安倍最后也已经典 ...

  8. C++随笔:.NET CoreCLR之GC探索(4)

    今天继续来 带大家讲解CoreCLR之GC,首先我们继续看这个GCSample,这篇文章是上一篇文章的继续,如果有不清楚的,还请翻到我写的上一篇随笔.下面我们继续: // Initialize fre ...

  9. C++随笔:.NET CoreCLR之GC探索(2)

    首先谢谢 @dudu 和 @张善友 这2位大神能订阅我,本来在写这个系列以前,我一直对写一些核心而且底层的知识持怀疑态度,我为什么持怀疑态度呢?因为一般写高层语言的人99%都不会碰底层,其实说句实话, ...

随机推荐

  1. Unity调用Android类方法

    Unity调用Android类方法 1.  添加Unity的classes.jar文件 创建一个Android工程AndroidUnityDemo. 由于Unity的版本不同,直接在Unity安装包文 ...

  2. Cesium原理篇:3最长的一帧之地形(4:重采样)

           地形部分的原理介绍的差不多了,但之前还有一个刻意忽略的地方,就是地形的重采样.通俗的讲,如果当前Tile没有地形数据的话,则会从他父类的地形数据中取它所对应的四分之一的地形数据.打个比方 ...

  3. 解决CHROME中画布中无法显示图片的方法

    最终效果图如下 我按照W3SCHOOL里面的方法,代码如下 <!DOCTYPE html> <html> <body> <script type=" ...

  4. POST方式提交表单时,后台接受实体如果继承了父类,将无法映射表单对应数据

    引言 刚才在做一个post提交表单时,我在表单里放了几个隐藏域用来存放数据,表单name属性和后台实体属性签名保持一致.只是后台Action参数包含继承关系,所以无法获取到表单对应的值.刚开始一直纳闷 ...

  5. WCF局域网内使用代理无法访问解决方法

    问题描述 在大部分事业单位上网都是需要使用代理的,前几天带着一个同事写的程序过来部署,部署以后各个客户端通过WCF相互通讯,那么其中一个地方在本地局域网测试是没有问题的. 后发现一部分是原因是由于代理 ...

  6. 【JUC】JDK1.8源码分析之ConcurrentHashMap(一)

    一.前言 最近几天忙着做点别的东西,今天终于有时间分析源码了,看源码感觉很爽,并且发现ConcurrentHashMap在JDK1.8版本与之前的版本在并发控制上存在很大的差别,很有必要进行认真的分析 ...

  7. Ueditor 增加模板

    简介: Ueditor 是百度出的开源富文本编辑器,非常符合国人习惯!模板功能很好用. 官网:http://ueditor.baidu.com/website/ 定义自己的模板: 先用Ueditor编 ...

  8. C++作用域

    作用域通常和变量捆绑在一起,限定了变量可用范围,同时也规定了变量的生命周期:何时创建.何时销毁.作用域通常分为:全局作用域和局部作用域. 全局作用域(全局变量) 在所用函数体外部定义的变量就是全局变量 ...

  9. Game中的状态机

    我相信大多数博友都会玩游戏. 玩游戏,牵涉到状态包含 登陆,正常,死亡,复活,下线, 在上面状态的基础上.同时包含 站立,走动,跑动,不可移动施法状态, 战斗状态, 通常这是三个不同的分组.也就说可以 ...

  10. .Net(c#)汉字和Unicode编码互相转换

    {"Tilte": "\u535a\u5ba2\u56ed", "Href": "http://www.cnblogs.com&q ...