Discuz!NT代码阅读笔记(4)--一切皆可配置:页面的显示
Discuz!NT代码阅读笔记(2)--网站安装也能自动化:论坛程序安装及初始化过程
Discuz!NT代码阅读笔记(3)--网站安装也能自动化--DNT安装时使用到的几个函数解析
Discuz!NT论坛程序具有强大的配置功能 :从论坛的标题到论坛各个地方的显示,论坛模板的使用等等。
1、ASP.NET页面事件执行过程
要弄明白DNT页面的显示过程,首先应知道ASP.NET页面事件的引发顺序。今天刚到手一本书:《ASP.NET3.5SP1高级编程》,上边是这么列的:
(1)PreInit
(2)Init
(3)InitComplate
(4)PreLoad
(5)Load
(6)LoadComplate
(7)PreRender
(8)PreRenderComplate
(9)UnLoad
也就是说在页面的生命周期内,ASP.NET就是按照这个顺序来执行的。当然,Page类的构造函数是最先执行的!
2、DNT页面的初始化过程
下面就以论坛首页(forumindex.aspx)的显示过程看一下DNT页面显示时是怎样将配置应用到页面中的。
首先,看该页的第一行:
<%@ Page Language="c#" AutoEventWireup="false" EnableViewState="false" Inherits="Discuz.Web.forumindex" %>
Inherits="Discuz.Web.forumindex":说明该页继承自Discuz.Web.forumindex这个类。这个类位于文件forumindex.aspx.cs中。
打开这个文件,可以看到这样的代码:
public class forumindex : PageBase
PageBase 继承自Page类,是DNT所有页面的基类。在文件forumindex.aspx.cs的forumindex类中定义了一些变量和两个函数:ShowPage()和GetSpacePerm()
ShowPage函数是这样定义的:
protected override void ShowPage()
{}
它重写了基类PageBase中的ShowPage()函数。前面说过,构造函数在所有函数前执行,而forumindex没有定义构造函数,初始化时将只执行基类的构造函数。而PageBase在构造函数中调用了ShowPage()函数,而派生类forumindex中覆盖了这个函数。所以forumindex中的ShowPage要在ASP.NET生命周期内的9个过程之前执行!
GetSpacePerm()函数是个人空间使用的函数,与论坛内容关系不大,暂不做介绍。
3、ShowPage函数中完成的工作
在ShowPage()函数中,DNT将显示页面需要的配置信息和从数据库读取的用户信息加载到内存中,用于以后的显示。
(1)设置页面的名称
pagetitle = "首页";
(2)加载用户组信息
AdminGroupInfo admingroupinfo = AdminGroups.GetAdminGroupInfo(usergroupid);
(3)写Cookie
ForumUtils.WriteCookie("isframe", "1");
(4)获取在线列表信息
OnlineUsers.UpdateAction(olid, UserAction.IndexShow.ActionID, 0, config.Onlinetimeout);
(5)获取当前用户的用户信息
userinfo = Users.GetShortUserInfo(userid);
(6)获取前台板块列表谈出菜单
navhomemenu = Caches.GetForumListMenuDivCache(usergroupid, userid, config.Extname);
(7)获取论坛的统计信息
totalusers = TypeConverter.StrToInt(Statistics.GetStatisticsRowItem("totalusers"));//总用户
lastusername = Statistics.GetStatisticsRowItem("lastusername").Trim();//最后发表用户
lastuserid = TypeConverter.StrToInt(Statistics.GetStatisticsRowItem("lastuserid"));//最后注册用户
yesterdayposts = TypeConverter.StrToInt(Statistics.GetStatisticsRowItem("yesterdayposts"));//昨日发帖数
highestposts = TypeConverter.StrToInt(Statistics.GetStatisticsRowItem("highestposts"));//最高发帖用户
highestpostsdate = Statistics.GetStatisticsRowItem("highestpostsdate").ToString().Trim();//最高发帖日期
(8)获取在线用户列表
onlineuserlist = OnlineUsers.GetOnlineUserCollection(out totalonline, out totalonlineguest, out totalonlineuser, out totalonlineinvisibleuser);
(9)获取论坛公告
announcementlist = Announcements.GetSimplifiedAnnouncementList(nowdatetime, "2999-01-01 00:00:00");
announcementcount = announcementlist != null ? announcementlist.Rows.Count : 0;
(10)从数据库中加载广告信息
headerad = Advertisements.GetOneHeaderAd("indexad", 0); //获取头部广告
footerad = Advertisements.GetOneFooterAd("indexad", 0); //获取底部广告
inforumad = Advertisements.GetInForumAd("indexad", 0, topforum, templatepath); //获取分类间广告
pagewordad = Advertisements.GetPageWordAd("indexad", 0); //获取页内文字广告
doublead = Advertisements.GetDoubleAd("indexad", 0); //对联广告
floatad = Advertisements.GetFloatAd("indexad", 0); //浮动广告
mediaad = Advertisements.GetMediaAd(templatepath, "indexad", 0); //Silverlight广告
广告方式还真多。。。。。
这些信息加载完之后,就可以在页面中显示了。
4、将页面显示出来(OnInit函数)
在 forumindex.aspx.cs的代码中没有一行是想浏览器输出的函数!加载了那么多信息之后,在哪显示呢?
打开文件首页的ASPX文件forumindex.aspx,可以看到字样的代码:
<script runat="server">
override protected void OnInit(EventArgs e)
{
}
</script>
OnInit对应于页面生命周期中的Init过程。DNT的PageBase类和其他页面类均有这样的函数。这个函数主要用于根据刚才加载的信息,向浏览器输出内容。
在OnInit()函数中DNT使用一个StringBuilder组织需要显示的内容,之后用Response.Write(templateBuilder.ToString());将内容输出到浏览器!
DNT的配置 功能都是在组织页面的这个StringBuilder中加入的!多完美!无缝加入!呵呵
附:关于DNT模板引擎的猜想
在OnInit()函数的执行过程中,DNT根据根据加载的信息,判断哪些内容是用户有权限查看的梦哪些内容用户没有权限查看。但像这样的写法实在是累,还容易出问题!看看DNT怎么做的吧:
/*
This page was created by Discuz!NT Template Engine at 2009-9-22 17:25:18.
本页面代码由Discuz!NT模板引擎生成于 2009-9-22 17:25:18.
*/
人家有模板引擎,自动生成的!我在想,为什么它能自动生成呢?
因为DNT的一切配置信息预先都设置好了。调用方法明确,函数名称清晰稳定。不需要再更改什么了!所以页面生成整个过程可能是这样的:
(1)总体设计时,明确哪些功能是可配置的。同时也明确实现这些配置功能的类。
(2)写配置函数。
(3)由页面设计者和美工做好完全功能的页面。
(4)整合。从页面文件中读取每一行的内容,加入判断信息后,添加到页面类的OnInit()函数中。
教我C# 的那个同事说DNT的架构师很牛!我写页面这么做跟架构师有关吧,架构师在设计之初就想到了这些功能!
写的不好,请大家见谅!有错误的地方或者语言组织不好的地方,还望各位老大多指正!