重温:从aspx到dll
今天开始,进一步深入学习asp.net,撇开ASP.NET MVC、LINQ等等,先把asp.net2.0给搞"精"咯。
书,看的是Dino Esposito的《ASP.NET2.0高级编程》,记得看的第一本asp.net的书也是Dino Esposito写的,在上个寒假,呵呵,虽然当时对书中讲到的asp.net编译模型有点抓狂,但他还是让我熟悉了aspx、控件和类之间的关系。虽然看书的时候自我感觉看懂了,但每次回头再看时,又会有不少新的认识,好书,也许就是越琢磨越有味道吧。
说正题吧:从aspx到dll,也许题目起的不是太恰当,主要就是温习一下一个asp.net应用程序从源代码到投入使用之间的那些事儿吧。
古老的ASP,在访问者每次浏览asp页面时,页面vbscript脚本都得重新被解释执行,但进入asp.net之后,就不是这样了,就像jsp一样,页面是会被编译的,当访问者第二次访问页面时,服务器所面对的,是已经编译好的托管代码,可不像asp时代那样每次都面对源代码。但是当我们用xCopy把应用拷到服务器上后,网站就可以被访问了,咦,编译后的那些东西,跑哪儿去了?恩,它们跑到了C盘的某个位置下。
我们都知道,一个aspx页面就是一个类,它继承自Page指令中Inhreits属性中指出的那个类,它一般就定义在对应的aspx.cs文件中,而aspx.cs中的那个类,又是从System.Web.UI.Page继承而来。
让我们打开站点根目录的web.config,找到<compilation debug="true">,把debug值设为true,然后"Build Web Site",然后再杀到C:\Windows\Microsoft.NET\Framework\v2.0.50727\Temporary ASP.NET Files文件夹下(当然,不一定所有人都把系统装在C盘,我是这个目录),里面有一些文件夹,其中有一个是跟我们的网站名同名,就是它了,点进去,再进入两层文件夹,就看到了一些以App_Web打头的cs文件,还有些以App_Web打头的dll,还有些.compiled文件,其中每三个cs文件都组成一组,在它们的文件名中有基于0的索引,这些cs文件,就是在网站被编译过程中的一些中间产物,先打开第"0"个cs文件(App_Web_***.0.cs),在上头的就是一个非常眼熟的partial类,它是我们aspx.cs文件中的分部类的另一半,可以看到,这个类中有一些protected的字段,它们就是我们拖在aspx页面中的控件,而字段名,就是我们在aspx页面中给它们取的ID名,哦,原来如些,虽然我把控件拖在aspx页面中,但它们在编译时其实是被拉到后面的aspx.cs文件中的那个类里面去了,而aspx继承于aspx.cs中的那个类,所以这些控件能在aspx中被访问(因为被声明成了protected),再回到前面的那个App_Web_***.0.cs 文件,往下拉,看到了namespace ASP,是定义了一个名为ASP的命名空间,再往下再往下,看到了一个***_aspx的类,它就是我们的aspx页面在编译时产生的了,如果aspx页面取名叫Index.aspx,那它就会被编译成index_aspx类(除非在Page指令中指定了ClassName属性),它继承自后台的aspx.cs文件中的那个类,它个***_aspx类中有一个名为FrameworkInitialize的方法,它调用了__BuildControlTree方法,看看__BuildControlTree,就知道它是干嘛用的了,下面还有一句:this.Request.ValidateInput();,啊哈,原来这里有验证用户请求,所以,一旦在aspx页面中输入一些非法字符(如<script>),页面就会报错,就是它搞的了,如果在aspx的page指定中设置ValidateRequest="false",那这就不会有这个验证了。***_aspx中还有个ProcessRequest方法,它是用来处理请求的。
好了,看了App_Web_***.0.cs,现在看App_Web_***.1.cs,它就是我们网站中的***.aspx.cs文件。再换,看App_Web_***.2.cs, 里面是一个FastObjectFactory_app_web_***的类,Factory,一个工厂类,它里头有个方法,里面只有一句return new ASP.***_aspx();,和和,是用来创建aspx页面(类)实例的。
上面这些就是中间编译的一部分中间产物,如果在web.config中设置<compilation debug="false">的话,这些文件在编译完成后会被删掉,只留下了一个App_Web_***.dll(在上面debug="true"的时候,.dll是多个)和几个***.aspx.***.compiled(有几个aspx就有几个.compiled),这个dll,就是我们的网站了,当它被加载到AppDomain中时,我们的网站就开始运作了。
先说这个.compiled是干嘛用的捏?恩,先用记事本把它打开…原来是一个xml文件,看里面的filedep,原来是aspx的位置,它是干嘛用的?其实呢,当我们把网站Copy到服务器中,在第一次浏览时,页面会被编译,然后,在Temporary ASP.NET Files文件夹下相应目录中就出现了.dll和.compiled,我们知道,当源代码被改动时,会导致网站被重新编译,这是比较笼统的说法,其实只要记录在.compiled中的那些文件被改动时,就会导致网站重新编译,我试着改动了一个aspx页面,然后Ctrl+S保存,马上,就看到在原先.dll所在目录下多了一个***.dll.delete文件,因为现在网站还在运行,所以dll删不得,于是,asp.net就搞了个.delete文件出来,标识一下,当再次Build Web Site时,就又多了一个.dll出来,现在,真正为浏览者服务的,是这个新的.dll,而原先那个虽然还呆在内存中不出来,但已经被革职了,时机成熟的时候,它就会被处死。那,是什么时候被处死呢?
在应用程序重新启动的时候它会被处死(和.delete一起),wait,什么叫应用程序重启?我们的dll是装在AppDomain中的,重启就是AppDomain被卸载,然后start over,dll是不能单独被卸载的,AppDomain卸载后,应用程序会被重新编译,然后干干净净装到新的AppDomain中,网站,又开始运作了。
那什么情况会导致应用程序重启?
一、web.config及global.asax这些应用程序文件被修改的时候;
二、当应用程序被重新编译15次(默认,可以改)之后。Note that,重新编译并不是应用程序重启,它只是会使得web应用被重新编译到一个dll中,然后搞个0kb的文件,文件名就是在旧的dll文件名后加上.delete,这就算给这个旧dll作了个记号,说这个dll是旧的,一会儿要记得把它丢垃圾桶去哈。但是,仁慈的我总不能对它见死不救,于是,我把这个.delete文件名给改了,在应用程序重启时,.delete是牺牲了,但那个旧dll留下来了,当然,它现在也已武功尽失,新dll已经代替了它的位置。
至此,今天的总结就差不多了。
THE END.