Community Server
专题六:Delegates & Events
对于CS的分析你可以能会从页面开始,其实那并不是一个很好的方法,因为CS采用了MasterPage和内建的Theme与Skins,页面一层嵌套一层,如果你对CS页面执行机制不了解,或者你是初学者,这个时候可能就会碰壁,接着就放弃了对CS更深入的了解。我希望我的专题能从CS的运行过程开始一步一步地讲解,同时把ASP.NET的运行机理也表述出来,因此学习了解CS的过程就是对ASP.NET深入了解得过程。当然,我个人的开发经验与水平也是有限的,如果在专题中表述有问题,或者有疑问可以直接在文章的评论中直接指出,我将万分感谢你。
在分析CSHttpModule.cs的时候,你会看到这样两句代码:
CSEvents.UserKnown(csContext.User);
CSEvents.CSException(csException);
其实短短两行代码后面隐藏了
Delegates与Events的大量运用,CS也通过这样的运用实现了一种模块化的处理机制,即CSModules。
打开
CommunityServerWeb项目下的communityserver.config文件,这是CS的配置文件(与Web.config不同,communityserver.config主要配置的是CS内部的一些运行机制,而Web.config主要配置的是与Asp.net的交互)。找到文件中的这段:
<
CSModules
>
< add name ="CSMembershipRulesModule" type ="CommunityServer.Components.CSMembershipRulesModule,CommunityServer.Components" />
< add name ="CSCatastrophicExceptionModule" type ="CommunityServer.Components.CSCatastrophicExceptionModule,CommunityServer.Components" />
< add name ="CSExceptionModule" type ="CommunityServer.Components.CSExceptionModule,CommunityServer.Components" />
< add name ="IrcCommands" type ="CommunityServer.Discussions.Components.IrcCommandsModule,CommunityServer.Discussions" />
< add name ="ForumCensorship" type ="CommunityServer.Discussions.Components.CensorshipModule,CommunityServer.Discussions" />
< add name ="ForumEmoticon" type ="CommunityServer.Discussions.Components.EmoticonModule,CommunityServer.Discussions" />
< add name ="ForumSourceCode" type ="CommunityServer.Discussions.Components.SourceCodeModule,CommunityServer.Discussions" />
< add name ="ForumHtmlScrubbing" type ="CommunityServer.Discussions.Components.HtmlScrubbingModule,CommunityServer.Discussions" />
< add name ="BBcodeToHtml" type ="CommunityServer.Discussions.Components.BBcodeToHtmlModule,CommunityServer.Discussions" />
< add name ="ForumPlainText" type ="CommunityServer.Discussions.Components.PlainTextModule,CommunityServer.Discussions" />
< add name ="WeblogCensorModule" type ="CommunityServer.Blogs.Components.CensorModule,CommunityServer.Blogs" />
< add name ="WeblogPostandArticleHtmlScrubbing" type ="CommunityServer.Blogs.Components.PostandArticleHtmlScrubbing,CommunityServer.Blogs" />
< add name ="WeblogFeedbackHtmlFormatting" type ="CommunityServer.Blogs.Components.FeedbackHtmlFormatting,CommunityServer.Blogs" />
< add name ="TrackbackModule" type ="CommunityServer.Blogs.Components.TrackbackModule,CommunityServer.Blogs" />
< add name ="XmlRpcPingModule" type ="CommunityServer.Blogs.Components.XmlRpcPingModule,CommunityServer.Blogs" />
< add name ="WeblogFormattingModule" type ="CommunityServer.Blogs.Components.WeblogFormattingModule,CommunityServer.Blogs" />
< add name ="PictureCensor" type ="CommunityServer.Galleries.Components.CensorPictureModule,CommunityServer.Galleries" />
< add name ="PictureHtmlScrubber" type ="CommunityServer.Galleries.Components.HtmlScrubberModule,CommunityServer.Galleries" />
< add name ="PictureComments" type ="CommunityServer.Galleries.Components.CommentModule,CommunityServer.Galleries" />
<!-- <addname="MaxPictureSize"type="CommunityServer.Galleries.Components.MaxPictureSizeModule,CommunityServer.Galleries"maxWidth="1024"maxHeight="768"quality="90"/> -->
</ CSModules >
< add name ="CSMembershipRulesModule" type ="CommunityServer.Components.CSMembershipRulesModule,CommunityServer.Components" />
< add name ="CSCatastrophicExceptionModule" type ="CommunityServer.Components.CSCatastrophicExceptionModule,CommunityServer.Components" />
< add name ="CSExceptionModule" type ="CommunityServer.Components.CSExceptionModule,CommunityServer.Components" />
< add name ="IrcCommands" type ="CommunityServer.Discussions.Components.IrcCommandsModule,CommunityServer.Discussions" />
< add name ="ForumCensorship" type ="CommunityServer.Discussions.Components.CensorshipModule,CommunityServer.Discussions" />
< add name ="ForumEmoticon" type ="CommunityServer.Discussions.Components.EmoticonModule,CommunityServer.Discussions" />
< add name ="ForumSourceCode" type ="CommunityServer.Discussions.Components.SourceCodeModule,CommunityServer.Discussions" />
< add name ="ForumHtmlScrubbing" type ="CommunityServer.Discussions.Components.HtmlScrubbingModule,CommunityServer.Discussions" />
< add name ="BBcodeToHtml" type ="CommunityServer.Discussions.Components.BBcodeToHtmlModule,CommunityServer.Discussions" />
< add name ="ForumPlainText" type ="CommunityServer.Discussions.Components.PlainTextModule,CommunityServer.Discussions" />
< add name ="WeblogCensorModule" type ="CommunityServer.Blogs.Components.CensorModule,CommunityServer.Blogs" />
< add name ="WeblogPostandArticleHtmlScrubbing" type ="CommunityServer.Blogs.Components.PostandArticleHtmlScrubbing,CommunityServer.Blogs" />
< add name ="WeblogFeedbackHtmlFormatting" type ="CommunityServer.Blogs.Components.FeedbackHtmlFormatting,CommunityServer.Blogs" />
< add name ="TrackbackModule" type ="CommunityServer.Blogs.Components.TrackbackModule,CommunityServer.Blogs" />
< add name ="XmlRpcPingModule" type ="CommunityServer.Blogs.Components.XmlRpcPingModule,CommunityServer.Blogs" />
< add name ="WeblogFormattingModule" type ="CommunityServer.Blogs.Components.WeblogFormattingModule,CommunityServer.Blogs" />
< add name ="PictureCensor" type ="CommunityServer.Galleries.Components.CensorPictureModule,CommunityServer.Galleries" />
< add name ="PictureHtmlScrubber" type ="CommunityServer.Galleries.Components.HtmlScrubberModule,CommunityServer.Galleries" />
< add name ="PictureComments" type ="CommunityServer.Galleries.Components.CommentModule,CommunityServer.Galleries" />
<!-- <addname="MaxPictureSize"type="CommunityServer.Galleries.Components.MaxPictureSizeModule,CommunityServer.Galleries"maxWidth="1024"maxHeight="768"quality="90"/> -->
</ CSModules >
我们拿出其中的一个来分析运行过程,例:
<addname="CSExceptionModule"type="CommunityServer.Components.CSExceptionModule, CommunityServer.Components"/>
这是
CS中异常处理的模块,当发生异常的时候该模块将调用一个RedirectToMessage方法,提示一个友好的错误界面,告诉请求的用户有错误发生。那么CS系统是如何在发生错误的时候自动调用RedirectToMessage方法转向另外一个页面提示友好错误的呢?先打开CommunityServerComponents项目下Components文件夹中的CSApplication.cs
using
System;
using System.Collections;
using System.ComponentModel;
using System.Web.Caching;
using System.Xml;
using CommunityServer.Configuration;
namespace CommunityServer.Components
{
Delegates#regionDelegates
//Dowewantonesingledelegateoracustomoneforeachtype
//publicdelegatevoidCSEventHandler(objectsender,CSEventArgse);
publicdelegatevoidCSUserEventHandler(Useruser,CSEventArgse);
publicdelegatevoidCSPostEventHandler(Postpost,CSEventArgse);
publicdelegatevoidCSSectionEventHandler(Sectionsection,CSEventArgse);
publicdelegatevoidCSGroupEventHandler(Groupgroup,CSEventArgse);
publicdelegatevoidCSExceptionHandler(CSExceptioncsEx,CSEventArgse);
#endregion
/**////<summary>
///SummarydescriptionforCSApplication.
///</summary>
publicclassCSApplication
{
privatemembers#regionprivatemembers
privateEventHandlerListEvents=newEventHandlerList();
privatestaticreadonlyobjectsync=newobject();
privateHashtablemodules=newHashtable();
#endregion
EventKeys(static)#regionEventKeys(static)
privatestaticobjectEventAuthorizePost=newobject();
privatestaticobjectEventPrePostUpdate=newobject();
privatestaticobjectEventPreProcessPost=newobject();
privatestaticobjectEventPostPostUpdate=newobject();
privatestaticobjectEventRatePost=newobject();
//privatestaticobjectEventPreRenderPost=newobject();
privatestaticobjectEventPreUserUpdate=newobject();
privatestaticobjectEventPostUserUpdate=newobject();
privatestaticobjectEventUserRemove=newobject();
privatestaticobjectEventUserKnown=newobject();
privatestaticobjectEventUserValidated=newobject();
privatestaticobjectEventPreSectionUpdate=newobject();
privatestaticobjectEventPostSectionUpdate=newobject();
privatestaticobjectEventPreSectionGroupUpdate=newobject();
privatestaticobjectEventPostSectionGroupUpdate=newobject();
privatestaticobjectEventUnhandledException=newobject();
#endregion
cnstr#regioncnstr
privateCSApplication()
{
}
internalstaticCSApplicationInstance()
{
conststringkey="CSApplication";
CSApplicationapp=CSCache.Get(key)asCSApplication;
if(app==null)
{
lock(sync)
{
app=CSCache.Get(key)asCSApplication;
if(app==null)
{
CSConfigurationconfig=CSContext.Current.Config;
XmlNodenode=config.GetConfigSection("CommunityServer/CSModules");
app=newCSApplication();
if(node!=null)
{
foreach(XmlNodeninnode.ChildNodes)
{
if(n.NodeType!=XmlNodeType.Comment)
{
switch(n.Name)
{
case"clear":
app.modules.Clear();
break;
case"remove":
app.modules.Remove(n.Attributes["name"].Value);
break;
case"add":
stringname=n.Attributes["name"].Value;
stringitype=n.Attributes["type"].Value;
Typetype=Type.GetType(itype);
if(type==null)
thrownewException(itype+"doesnotexist");
ICSModulemod=Activator.CreateInstance(type)asICSModule;
if(mod==null)
thrownewException(itype+"doesnotimplementICSModuleorisnotconfiguredcorrectly");
mod.Init(app,n);
app.modules.Add(name,mod);
break;
}
}
}
}
CacheDependencydep=newCacheDependency(null,newstring[]{CSConfiguration.CacheKey});
CSCache.Max(key,app,dep);
}
}
using System.Collections;
using System.ComponentModel;
using System.Web.Caching;
using System.Xml;
using CommunityServer.Configuration;
namespace CommunityServer.Components
{
Delegates#regionDelegates
//Dowewantonesingledelegateoracustomoneforeachtype
//publicdelegatevoidCSEventHandler(objectsender,CSEventArgse);
publicdelegatevoidCSUserEventHandler(Useruser,CSEventArgse);
publicdelegatevoidCSPostEventHandler(Postpost,CSEventArgse);
publicdelegatevoidCSSectionEventHandler(Sectionsection,CSEventArgse);
publicdelegatevoidCSGroupEventHandler(Groupgroup,CSEventArgse);
publicdelegatevoidCSExceptionHandler(CSExceptioncsEx,CSEventArgse);
#endregion
/**////<summary>
///SummarydescriptionforCSApplication.
///</summary>
publicclassCSApplication
{
privatemembers#regionprivatemembers
privateEventHandlerListEvents=newEventHandlerList();
privatestaticreadonlyobjectsync=newobject();
privateHashtablemodules=newHashtable();
#endregion
EventKeys(static)#regionEventKeys(static)
privatestaticobjectEventAuthorizePost=newobject();
privatestaticobjectEventPrePostUpdate=newobject();
privatestaticobjectEventPreProcessPost=newobject();
privatestaticobjectEventPostPostUpdate=newobject();
privatestaticobjectEventRatePost=newobject();
//privatestaticobjectEventPreRenderPost=newobject();
privatestaticobjectEventPreUserUpdate=newobject();
privatestaticobjectEventPostUserUpdate=newobject();
privatestaticobjectEventUserRemove=newobject();
privatestaticobjectEventUserKnown=newobject();
privatestaticobjectEventUserValidated=newobject();
privatestaticobjectEventPreSectionUpdate=newobject();
privatestaticobjectEventPostSectionUpdate=newobject();
privatestaticobjectEventPreSectionGroupUpdate=newobject();
privatestaticobjectEventPostSectionGroupUpdate=newobject();
privatestaticobjectEventUnhandledException=newobject();
#endregion
cnstr#regioncnstr
privateCSApplication()
{
}
internalstaticCSApplicationInstance()
{
conststringkey="CSApplication";
CSApplicationapp=CSCache.Get(key)asCSApplication;
if(app==null)
{
lock(sync)
{
app=CSCache.Get(key)asCSApplication;
if(app==null)
{
CSConfigurationconfig=CSContext.Current.Config;
XmlNodenode=config.GetConfigSection("CommunityServer/CSModules");
app=newCSApplication();
if(node!=null)
{
foreach(XmlNodeninnode.ChildNodes)
{
if(n.NodeType!=XmlNodeType.Comment)
{
switch(n.Name)
{
case"clear":
app.modules.Clear();
break;
case"remove":
app.modules.Remove(n.Attributes["name"].Value);
break;
case"add":
stringname=n.Attributes["name"].Value;
stringitype=n.Attributes["type"].Value;
Typetype=Type.GetType(itype);
if(type==null)
thrownewException(itype+"doesnotexist");
ICSModulemod=Activator.CreateInstance(type)asICSModule;
if(mod==null)
thrownewException(itype+"doesnotimplementICSModuleorisnotconfiguredcorrectly");
mod.Init(app,n);
app.modules.Add(name,mod);
break;
}
}
}
}
CacheDependencydep=newCacheDependency(null,newstring[]{CSConfiguration.CacheKey});
CSCache.Max(key,app,dep);
}
}