带你读开源—ASP.NET_MVC(六)
来源:互联网 发布:c语言指针和引用 编辑:程序博客网 时间:2024/05/29 16:25
我们接着上一篇的进度,跟进到“带你读开源—ASP.NET_MVC(五)”代码段6中的Execute()方法的定义,发现它是WebPageExecutingBase类的一个抽象方法,而且我找遍了整个MVC源码,也没有找到Execute()方法的具体重写版本。我靠!一个抽象方法没有任何地方重写它,这是“什么鬼”?于是乎,我苦苦哀求度娘指点迷津,她老人家凭借渊博的知识给了我答案。还记得上一篇上标[1]处那个悬念吗?.cshtml文件不能直接执行,但是MVC把它即时翻译为一个类,这个类可以C:\Users\你的登录名\AppData\Local\Temp\Tempporary ASP.NET Files下找到,它的文件名一般是形如App_Web_xvagnor1.1.cs。代码段1是一个Razor视图脚本,代码段2是代码段1经过即时翻译生成的C#类。
@model string[]@{ViewBag.Title = "Index";}这只是一大堆人名,不是名人:@foreach (string name in Model) {<span><b>@name</b></span>}
代码段 1
public class _Page_Views_Home_Index_cshtml :System.Web.Mvc.WebViewPage<string[]>{public_Page_Views_Home_Index_cshtml(){}public override void Execute(){WriteLiteral("\r\n");ViewBag.Title ="Index";WriteLiteral("\r\n这只是一大堆人名,不是名人:\r\n\r\n");foreach (string name in Model){WriteLiteral("<span><b>");Write(name);WriteLiteral("</b></span>\r\n");}}}
代码段 2
我们看代码段2所示的_Page_Views_Home_Index_cshtml类继承自System.Web.Mvc.WebViewPage<string[]>类,它有一个Execute方法的override,这不就是第一段中我们苦苦找寻的那个Execute重写的“什么鬼”吗?
好吧,我承认,这里的跨度有点大,大家喝口水压压惊,小心别扯着“淡”,嘿嘿!我再给大家好好捋捋,也就是说:ActionResultàViewResult的ExecuteResult方法àBuildManagerCompiledView的Render方法àBuildManagerCompiledView的RenderView方法àWebViewPage的ExecutePageHierarchy方法àWebViewPage的Execute抽象方法à视图即时翻译类_Page_Views_Home_Index_cshtml的Execute方法。到这里,视图引擎寻找视图、翻译视图、发回响应就全部完成了。
回过头来我们再看一下代码段2,类_Page_Views_Home_Index_cshtml的命名规则很有意思,首先它很长,其次它用下划线分割,意思是:这个类是一个页面视图,控制器是Home,Action是Index,是一个C#的类。在这个类里,cshtml中带@的代码原样输出,Html标记用WriteLiteral方法进行处理,该方法的定义在WebPageBase类的定义中,见代码段3,作用就是向浏览器发回HTML响应报文。
public override voidWriteLiteral(object value) { Output.Write(value); }
代码段 3
OK,到此为止,ASP.NET MVC的请求处理管线已经大概分析完了,啰哩啰唆,没有什么条理,想到那写到哪,大家别见笑。看到这,有人会以为这个系列有可能结束了,那么我告诉你,还早呢!想甩掉我,没门,哈哈!
------------------------我只是一条华丽的分割线--------------------------
从现在开始,我们开始离开主线,来到分支,查漏补缺,分析细节。
麻烦各位翻到在下的上一篇文章“带你读开源—ASP.NET_MVC(五)”,找到代码段3中的①【instance = ViewPageActivator.Create(_controllerContext, type);】。这句话意思是利用反射机制创建WebViewPage的实例,我们转到Create的定义,发现它是一个接口方法,见代码段4。
public interface IViewPageActivator { object Create(ControllerContextcontrollerContext, Type type); }
代码段 4
和往常一样,在源码里找IViewPageActivator的具体实现类,发现只有一个DefaultViewPageActivator类实现了该接口,见代码段5。
public objectCreate(ControllerContext controllerContext, Type type) { try { return_resolverThunk().GetService(type) ?? Activator.CreateInstance(type); } catch (MissingMethodExceptionexception) { // Ensure thrown exceptioncontains the type name. Might be down afew levels. MissingMethodExceptionreplacementException = TypeHelpers.EnsureDebuggableException(exception, type.FullName); if (replacementException !=null) { throwreplacementException; } throw; } }
代码段 5
代码段5的核心代码是【return _resolverThunk().GetService(type) ??Activator.CreateInstance(type);】,即利用反射来实例化type所代表的类型。那么这个type从哪里来的呢?我们在“带你读开源—ASP.NET_MVC(五)”的代码段3中找到【Type type =BuildManager.GetCompiledType(ViewPath);】这个语句,转到GetCompiledType的定义,发现它也是一个接口IBuildManager的方法(代码段6),而BuildManagerWrapper类实现了该接口(代码段7),BuildManager.GetCompiledType方法是系统预置的静态方法,作用是把我们的视图文件(cshtml)即时编译并返回编译得到的类型,这是这句话把代码段1翻译成了代码段2。
internal interface IBuildManager { bool FileExists(string virtualPath); Type GetCompiledType(stringvirtualPath); ICollection GetReferencedAssemblies(); Stream ReadCachedFile(string fileName); Stream CreateCachedFile(stringfileName); }
代码段 6
TypeIBuildManager.GetCompiledType(string virtualPath) { return BuildManager.GetCompiledType(virtualPath); }
代码段 7
- 带你读开源—ASP.NET_MVC(六)
- 带你读开源—ASP.NET_MVC(一)
- 带你读开源—ASP.NET_MVC(二)
- 带你读开源—ASP.NET_MVC(三)
- 带你读开源—ASP.NET_MVC(四)
- 带你读开源—ASP.NET_MVC(五)
- 带你读开源—ASP.NET_MVC(七)
- 带你读开源—ASP.NET_MVC(八)
- 带你读开源—ASP.NET_MVC(九)
- 带你读开源—ASP.NET_MVC(十)
- 带你读开源—ASP.NET_MVC(十一)
- 带你读开源—ASP.NET_MVC(十二)
- 带你读开源—ASP.NET_MVC(十三)
- 带你读开源—ASP.NET_MVC(十四)
- 带你读开源—ASP.NET_MVC(十五)
- ASP.NET_MVC
- .NET_MVC
- 墨香带你学Launcher之(六)- 拖拽
- AndroidStudio 中如何导入和删除jar包
- ServletContext的讲解
- 自定义View之仿淘宝详情页
- Android设置空间的透明度
- ccf201604-4 游戏
- 带你读开源—ASP.NET_MVC(六)
- 【SDL】SDL简介
- 服务器返回到浏览器的常见信息
- 工作流Activiti的学习总结(五) activiti的API和虚拟工作流测试
- Android从上往下滑动或从下往上滑动结束Activity
- Media Data之多媒体数据库(二)MediaProvider
- 关于天嵌2440提供的jflash工程不能连接开发板的问题
- 多级目录makefile例子
- 求本月的第一个周一