测试实例如下:

前台代码MyFirstWeb.aspx(没有服务器控件,即没有runat)

CodeBehind=”MyFirstWeb.aspx.cs”:表示代码后置类文件
Inherits=”SimpleWeb.MyfirstWeb”:表示该前台类继承于代码后置类文件中的哪个类
<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="MyFirstWeb.aspx.cs" Inherits="SimpleWeb.MyFirstWeb" %>

<!DOCTYPE html>

<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
<title></title>
</head>
<body>
<!--获取前台页面的程序集位置-->
<%=this.GetType().Assembly.Location %>
<form id="form1">
<div>
<input type="text" name="txtName"/>
<input type="submit" id="btnClick"/>
</div>
</form>
</body>
</html>

后台代码

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls; namespace SimpleWeb
{
public partial class MyFirstWeb : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
Response.Write("Page_Load方法的开始<br/>");
Response.Write("Page_Load方法的结束<br/>");
}
}
}

一个前台页面文件,在第一次被访问时,会被编译成一个类

前台页面会被编译成前台页面类myfirstweb_aspx继承于后台页面类MyFirstWeb.cs

发现前台类实现了IRequesSessionState:要取出Session中值,需要改接口

又实现了IHttpHandler:因为后台类继承于Page,Page已经实现了该接口,此处只为方便阅读而已
public class myfirstweb_aspx : MyFirstWeb, IRequiresSessionState, IHttpHandler
{
// Fields
private static object __fileDependencies;
private static bool __initialized;
private static MethodInfo __PageInspector_BeginRenderTracingMethod;
private static MethodInfo __PageInspector_EndRenderTracingMethod;
private static MethodInfo __PageInspector_SetTraceDataMethod; // Methods
static myfirstweb_aspx();
[DebuggerNonUserCode]
public myfirstweb_aspx();
[DebuggerNonUserCode]
private HtmlHead __BuildControl__control2();
[DebuggerNonUserCode]
private HtmlMeta __BuildControl__control3();
[DebuggerNonUserCode]
private HtmlTitle __BuildControl__control4();
[DebuggerNonUserCode]
private void __BuildControlTree(myfirstweb_aspx __ctrl);
private void __PageInspector_BeginRenderTracing(object[] parameters);
private void __PageInspector_EndRenderTracing(object[] parameters);
private static MethodInfo __PageInspector_LoadHelper(string helperName);
private void __PageInspector_SetTraceData(object[] parameters);
private void __Render__control1(HtmlTextWriter __w, Control parameterContainer);
[DebuggerNonUserCode]
protected override void FrameworkInitialize();
[DebuggerNonUserCode]
public override int GetTypeHashCode();
[DebuggerNonUserCode]
public override void ProcessRequest(HttpContext context); // Properties
protected HttpApplication ApplicationInstance { get; }
protected DefaultProfile Profile { get; }
}

后台页面类MyFirstWeb.cs,如下

public class MyFirstWeb : Page
{
// Fields
protected HtmlForm form1; // Methods
protected void Page_Load(object sender, EventArgs e)
{
base.Response.Write("Page_Load方法的开始<br/>");
base.Response.Write("Page_Load方法的结束<br/>");
}
}

-------------------------------------------------------------开始分析源码-----------------------------------------------------------------------------------

1.当在浏览框中输入Localhost:MyFirstWeb.aspx,按回车的时候,

在请求管道的第8个事件,创建了与请求名同名的页面类对象myfirstweb_aspx.cs,

然后将该页面类对象保存到HttpContext中的RemapHandler中。

接着在管道的第11个事件和12个事件之间,调用页面对象的PR方法,

因为前台页面类继承于后台类,而后台类有继承于Page类,所以实际调用的是Page类的PR方法。

private void ProcessRequest()
{
Thread currentThread = Thread.CurrentThread;
CultureInfo currentCulture = currentThread.CurrentCulture;
CultureInfo currentUICulture = currentThread.CurrentUICulture;
try
{
this.ProcessRequest(true, true);
}
finally
{
this.RestoreCultures(currentThread, currentCulture, currentUICulture);
}
}

1.1继续调用它的重载函数的PR方法

this.FrameworkInitialize(); 表示调用当前对象的FI方法,当前对象就是前台页面类,那么我们就转到前台页面类的FI方法看看;

protected override void FrameworkInitialize(); 发现在前台页面类中,重写了其父类的FI方法
private void ProcessRequest(bool includeStagesBeforeAsyncPoint, bool includeStagesAfterAsyncPoint)
{
if (includeStagesBeforeAsyncPoint)
{
this.FrameworkInitialize();
base.ControlState = ControlState.FrameworkInitialized;
}
bool flag = this.Context.WorkerRequest is IIS7WorkerRequest;
try
{
try
{
if (this.IsTransacted)
{
this.ProcessRequestTransacted();
}
else
{
this.ProcessRequestMain(includeStagesBeforeAsyncPoint, includeStagesAfterAsyncPoint);
}
if (includeStagesAfterAsyncPoint)
{
flag = false;
this.ProcessRequestEndTrace();
}
}
catch (ThreadAbortException)
{
try
{
if (flag)
{
this.ProcessRequestEndTrace();
}
}
catch
{
}
}
finally
{
if (includeStagesAfterAsyncPoint)
{
this.ProcessRequestCleanup();
}
}
}
catch
{
throw;
}
}

2.FI方法,代码如下

this.__BuildControlTree(this); 将前台页面对象作为参数传入,开始创建控件树
[DebuggerNonUserCode]
protected override void FrameworkInitialize()
{
base.FrameworkInitialize();
this.__BuildControlTree(this);
base.AddWrappedFileDependencies(__fileDependencies);
base.Request.ValidateInput();
}

2.1.__BuildControlTree()代码如下

myfirstweb_aspx __ctrl:那么_ctrl就是前台页面类;

IParserAccessor __parser = __ctrl:将_ctrl转为接口类型,那么此时_parser就是前台页面类;

__parser.AddParsedSubObject(__ctrl1):将_ctrl1添加到前台页面类中。

                                            问题一:_ctrl1是什么类型?还有它被添加到前台页面类的哪个成员中?

[DebuggerNonUserCode]
private void __BuildControlTree(myfirstweb_aspx __ctrl)
{
this.InitializeCulture();
HtmlHead __ctrl1 = this.__BuildControl__control2();
IParserAccessor __parser = __ctrl;
__parser.AddParsedSubObject(__ctrl1);
__ctrl.SetRenderMethodDelegate(new RenderMethod(this.__Render__control1));
}

2.1.1.__BuildControl__control2();代码如下

HtmlHead __ctrl = new HtmlHead("head"):创建一个head标签,并添加到前台页面类中;

HtmlMeta __ctrl1 = this.__BuildControl__control3():设置meta的属性,并添加到head中;

HtmlTitle __ctrl2 = this.__BuildControl__control4():设置标题,并返回标题,然后添加到前台页面对象中;
[DebuggerNonUserCode]
private HtmlHead __BuildControl__control2()
{
HtmlHead __ctrl = new HtmlHead("head");
HtmlMeta __ctrl1 = this.__BuildControl__control3();
IParserAccessor __parser = __ctrl;
__parser.AddParsedSubObject(__ctrl1);
HtmlTitle __ctrl2 = this.__BuildControl__control4();
__parser.AddParsedSubObject(__ctrl2);
object[] CS$0$0001 = new object[5];
CS$0$0001[0] = __ctrl;
CS$0$0001[2] = 180;
CS$0$0001[3] = 0x79;
CS$0$0001[4] = false;
this.__PageInspector_SetTraceData(CS$0$0001);
return __ctrl;
}

2.1.2.SetRenderMethodDelegate(new RenderMethod());调用一个委托,RenderMethod代码如下

__w.Write:生成的代码写入了一个字符数组中(详情看超链接,文章后续会发布),当输出的时候,也是按写入时的顺序;

__w.Write(base.GetType().Assembly.Location):很熟悉,就是我们在前台中写的C#代码,照样写入到字符数组中;

parameterContainer.Controls[0].RenderControl(__w):在控件容器中找到第一个控件,然后调用它的RenderControl方法,

                                                                                                   在开始创建控件树时,发现第一个被添加到控件容器的是HTMLHead

RenderControl(__w):也是吧代码写到字符数组中,不信自己看看源码

private void __Render__control1(HtmlTextWriter __w, Control parameterContainer)
{
this.__PageInspector_BeginRenderTracing(new object[] { __w, "/MyFirstWeb.aspx", 0x70, 0x44, true });
__w.Write("\r\n\r\n<!DOCTYPE html>\r\n\r\n<html xmlns=\"http://www.w3.org/1999/xhtml\">\r\n");
this.__PageInspector_EndRenderTracing(new object[] { __w });
parameterContainer.Controls[0].RenderControl(__w);
this.__PageInspector_BeginRenderTracing(new object[] { __w, "/MyFirstWeb.aspx", 0x12d, 0x27, true });
__w.Write("\r\n<body>\r\n <!--获取前台页面的程序集位置-->\r\n ");
this.__PageInspector_EndRenderTracing(new object[] { __w });
this.__PageInspector_BeginRenderTracing(new object[] { __w, "/MyFirstWeb.aspx", 340, 0x26, false });
__w.Write(base.GetType().Assembly.Location);
this.__PageInspector_EndRenderTracing(new object[] { __w });
this.__PageInspector_BeginRenderTracing(new object[] { __w, "/MyFirstWeb.aspx", 0x17a, 0xa7, true });
__w.Write("\r\n <form id=\"form1\" >\r\n <div>\r\n <input type=\"text\" name=\"txtName\"/>\r\n <input type=\"submit\" id=\"btnClick\"/>\r\n </div>\r\n </form>\r\n</body>\r\n</html>\r\n");
this.__PageInspector_EndRenderTracing(new object[] { __w });
}

---------------------------------------------------------------问题解答--------------------------------------------------------------------------------------

问题一:_ctrl1是什么类型?还有它被添加到前台页面类的哪个成员中?

_ctrl1是前台页面类型,那么前台页面又是什么类型

myfirstweb_aspx继承于MyFirstWeb;

MyFirstWeb继承于Page;

Page继承于TemplateControl;(那么也可以说Page类也是一个控件)

TemplateControl继承于Control;

Control中有个只读属性,类型是控件集合类型:public virtual ControlCollection Controls { get; }

那么一切问题都解决了,通过创建控件树,创建了一个个控件,同时将这些控件依次添加到前台页面的控件集合中,然后依次调用控件的RenderControl方法,将结果添加到字符数组中,然后将字符数组输出给HttpRuntime,然后传给iis,最后返回给浏览器,浏览器在根据接收到的结果,渲染界面,这就是我们最终看到的。

源码如下,就是按照字符数组中先后添加的代码显示到界面。为什么Page_Load中的数据先输出,请看超链接,文章后续会发布

Page_Load方法的开始<br/>Page_Load方法的结束<br/>

<!DOCTYPE html>

<html xmlns="http://www.w3.org/1999/xhtml">
<head><meta http-equiv="Content-Type" content="text/html; charset=utf-8" /><title> </title></head>
<body>
<!--获取前台页面的程序集位置-->
D:\Users\Kimisme\AppData\Local\Temp\Temporary ASP.NET Files\root\5f14d39c\6593da16\App_Web_4br2rhb1.dll
<form id="form1" >
<div>
<input type="text" name="txtName"/>
<input type="submit" id="btnClick"/>
</div>
</form> <!-- Visual Studio Browser Link -->
<script type="application/json" id="__browserLink_initializationData">
{"appName":"InternetExplorer","requestId":"6cd255e00ebe439facbd972bb23ed352"}
</script>
<script type="text/javascript" src="http://localhost:1090/86ceaccf0cf9404491a3a03bf9ab677a/browserLink" async="async"></script>
<!-- End Browser Link --> </body>
</html>

最新文章

  1. 我的java后端书架
  2. Find the largest K numbers from array (找出数组中最大的K个值)
  3. [Angularjs]asp.net mvc+angularjs+web api单页应用之CRUD操作
  4. respberry pi3 上手随记
  5. 跟我一起学WCF(13)——WCF系列总结
  6. Javascript构造函数与prototype
  7. 插入随机数到MySQL数据库
  8. Unity3d修改FBX文件的动画名方法
  9. CSS3—三角形
  10. 编程实现Windows关机、重启、注销
  11. 第三方app抽奖发送微信红包
  12. PHP和JS判断变量是否定义
  13. KnockOut 绑定之foreach绑定
  14. CF1131D Gourmet choice
  15. update_engine-整体结构(二)
  16. 做项目单个功能的时候要理解需求和sql语句。
  17. Maven提示找不到dependency依赖包
  18. 再读c++primer plus 005
  19. sso接口的调用
  20. 一种高效的序列化方式——MessagePack

热门文章

  1. linux 简单实用小操作
  2. 零基础到架构师 不花钱学JavaEE(基础篇)- 概述
  3. noip模拟赛 洗澡
  4. 【网络流24题】最长k可重区间集问题(费用流)
  5. vue组件知识总结
  6. 最小生成树 E - QS Network
  7. BAT经典面试题,深入理解Java内存模型JMM
  8. 6、Java并发性和多线程-并发性与并行性
  9. ojdbc.jar
  10. NetCore实现全局异常捕捉统一处理