带你读开源—ASP.NET_MVC(六)

原创 2016年08月29日 14:53:43

        我们接着上一篇的进度,跟进到“带你读开源—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.NETMVC项目都包含一个Global.asax文件,这个文件代码很少,只包括三个方法,即RegisterGlobalFilters、Registe...
  • CKAOS
  • CKAOS
  • 2016年09月09日 20:47
  • 693

带你读开源—ASP.NET_MVC(二)

上篇文章从整体上介绍了ASP.NET MVC的请求处理流程,大概分为“路由”、“控制器”、“视图”以及“模型”,下面便按照流程依次展开。         一、路由         提到路由,实际上分为...
  • CKAOS
  • CKAOS
  • 2016年08月25日 20:40
  • 588

带你读开源—ASP.NET_MVC(十)

今天研究一下HtmlHelper,ASP.NET MVC框架有数量众多的Helper,包括内置的和用户自己定义的,这些Helper的存在,极大方便了实际开发。我们最为熟悉的莫过于HtmlHelper....
  • CKAOS
  • CKAOS
  • 2016年09月09日 21:02
  • 382

带你读开源—ASP.NET_MVC(三)

上篇说到ControllerActionInvoker的InvokeAction方法,今天继续。         谈点题外话,MVC中大量使用接口和IOC,即控制反转(或依赖注入),这个我们留个专题讨...
  • CKAOS
  • CKAOS
  • 2016年08月25日 21:02
  • 722

带你读开源—ASP.NET_MVC(四)

上篇聊到ActionResult的ExecuteResult方法,今天继续。         我们首先看一下ActionResult的定义(代码段1),它是一个抽象类,只有一个抽象方法ExecuteR...
  • CKAOS
  • CKAOS
  • 2016年08月25日 21:12
  • 970

带你读开源—ASP.NET_MVC(五)

书接上文,我们继续跟踪CreateView方法,发现它是一个抽象方法,好吧,我们发现BuildManagerViewEngine继承了VirtualPathProviderViewEngine,但是它...
  • CKAOS
  • CKAOS
  • 2016年08月27日 12:38
  • 893

带你读开源—ASP.NET_MVC(十三)

今天紧接上篇的进度,继续讨论ModelBinding。         为了衔接顺畅,把上篇最后一段代码再贴一遍,姑且称作代码段1吧。   protected virtual obje...
  • CKAOS
  • CKAOS
  • 2016年09月14日 20:08
  • 320

带你读开源—ASP.NET_MVC(十四)

上回书说到ModelBinderDictionary类的GetBinder方法的实现原理,今天继续解释第四条注释。         4、用户提供的备用Binder         这一条很简单,f...
  • CKAOS
  • CKAOS
  • 2016年09月18日 20:18
  • 281

带你读开源—ASP.NET_MVC(十五)

上篇讨论了BindSimpleModel方法,今天我们看一下BindComplexModel方法。代码段1为BindComplexModel方法的定义,执行过程是:首先检查请求的参数类型,依次按照数组...
  • CKAOS
  • CKAOS
  • 2016年09月22日 20:34
  • 343

带你读开源—ASP.NET_MVC(八)

上篇说到GetControllerTypeWithinNamespaces方法,我们跟踪进入其定义后,发现其调用了ControllerTypeCache.GetControllerTypes方法,从C...
  • CKAOS
  • CKAOS
  • 2016年09月09日 20:50
  • 324
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:带你读开源—ASP.NET_MVC(六)
举报原因:
原因补充:

(最多只允许输入30个字)