Community Server专题六:Delegates & Events

本文详细解析了CommunityServer (CS) 中如何利用委托(Delegates)与事件(Events)实现模块化异常处理机制。通过具体代码示例和配置文件解释了CS如何在发生异常时自动调用特定模块的方法,展示了一个友好的错误处理界面。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

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>

<addname="CSMembershipRulesModule"type="CommunityServer.Components.CSMembershipRulesModule,CommunityServer.Components"/>

<addname="CSCatastrophicExceptionModule"type="CommunityServer.Components.CSCatastrophicExceptionModule,CommunityServer.Components"/>

<addname="CSExceptionModule"type="CommunityServer.Components.CSExceptionModule,CommunityServer.Components"/>

<addname="IrcCommands"type="CommunityServer.Discussions.Components.IrcCommandsModule,CommunityServer.Discussions"/>

<addname="ForumCensorship"type="CommunityServer.Discussions.Components.CensorshipModule,CommunityServer.Discussions"/>

<addname="ForumEmoticon"type="CommunityServer.Discussions.Components.EmoticonModule,CommunityServer.Discussions"/>

<addname="ForumSourceCode"type="CommunityServer.Discussions.Components.SourceCodeModule,CommunityServer.Discussions"/>

<addname="ForumHtmlScrubbing"type="CommunityServer.Discussions.Components.HtmlScrubbingModule,CommunityServer.Discussions"/>

<addname="BBcodeToHtml"type="CommunityServer.Discussions.Components.BBcodeToHtmlModule,CommunityServer.Discussions"/>

<addname="ForumPlainText"type="CommunityServer.Discussions.Components.PlainTextModule,CommunityServer.Discussions"/>



<addname="WeblogCensorModule"type="CommunityServer.Blogs.Components.CensorModule,CommunityServer.Blogs"/>

<addname="WeblogPostandArticleHtmlScrubbing"type="CommunityServer.Blogs.Components.PostandArticleHtmlScrubbing,CommunityServer.Blogs"/>

<addname="WeblogFeedbackHtmlFormatting"type="CommunityServer.Blogs.Components.FeedbackHtmlFormatting,CommunityServer.Blogs"/>

<addname="TrackbackModule"type="CommunityServer.Blogs.Components.TrackbackModule,CommunityServer.Blogs"/>

<addname="XmlRpcPingModule"type="CommunityServer.Blogs.Components.XmlRpcPingModule,CommunityServer.Blogs"/>

<addname="WeblogFormattingModule"type="CommunityServer.Blogs.Components.WeblogFormattingModule,CommunityServer.Blogs"/>

<addname="PictureCensor"type="CommunityServer.Galleries.Components.CensorPictureModule,CommunityServer.Galleries"/>

<addname="PictureHtmlScrubber"type="CommunityServer.Galleries.Components.HtmlScrubberModule,CommunityServer.Galleries"/>

<addname="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
usingSystem;

usingSystem.Collections;

usingSystem.ComponentModel;

usingSystem.Web.Caching;

usingSystem.Xml;

usingCommunityServer.Configuration;



namespaceCommunityServer.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);

}






}

&lt;think&gt;好的,用户遇到了一个CS1061错误,具体是在使用vbe.Events.WindowActivated的时候。我需要先确定这个错误的原因。CS1061通常是指某个对象没有某个成员,也就是可能缺少方法或属性。用户之前在使用VSTO开发VBE编辑器的行号功能,所以可能是在引用VBE扩展库时出了问题。首先,我应该检查用户是否正确引用了Microsoft.Vbe.Interop库。这个库是VBA扩展性的一部分,可能没有正确添加到项目中。另外,不同版本的Office可能对应的库版本不同,如果用户用的是较新版本的Office,可能需要检查是否有兼容性问题。然后,用户代码中的vbe.Events.WindowActivated事件订阅是否正确。VBE的事件模型可能在不同版本中有变化,比如某些事件可能被移动或改名。例如,可能应该使用VBEEvents而不是直接通过Events属性访问。或者用户可能需要先获取VBE的事件对象,再订阅具体的事件。另外,用户是否在代码中正确获取了VBE实例?比如Application.VBE在某些情况下可能返回null,导致后续调用事件时出现错误。需要确保Application对象正确初始化,并且有权限访问VBE对象模型。 还有可能用户没有启用&ldquo;信任对VBA工程对象模型的访问&rdquo;,这在Excel的安全设置里需要手动开启,否则无法访问VBE的相关对象,导致类型不识别。我应该建议用户检查引用,确保Microsoft.Vbe.Interop正确添加,并且版本与Office安装版本一致。同时,检查代码中的事件订阅方式是否正确,可能需要使用VBEEvents接口来访问WindowActivated事件。另外,提醒用户检查Office的安全设置,确保权限允许访问VBE对象。最后,可能需要提供示例代码,展示如何正确获取事件,或者使用动态类型来避免编译时的类型检查错误,比如将vbe.Events转换为dynamic类型,但这可能不是最佳实践。或者建议用户使用特定的接口来访问事件,比如通过vbe.Events.Get&lt;VBEEvents&gt;()这样的方法,具体取决于库的结构。 总结,用户的问题可能出在缺少正确的库引用或事件订阅方式错误,需要指导用户检查这些方面,并提供正确的代码示例和配置步骤。&lt;/think&gt;以下是解决VBE事件CS1061错误的详细方案: ```csharp // 正确的事件订阅方式(需要引用Microsoft.Vbe.Interop 1.1) private void SubscribeVbeEvents() { // 获取VBE对象 var vbe = Application.VBE; // 正确的事件绑定方式 var vbeEvents = vbe.Events as VBEEvents; if (vbeEvents != null) { vbeEvents.WindowActivated += OnWindowActivated; } else { MessageBox.Show(&quot;无法获取VBEEvents对象&quot;); } } // 正确的事件处理方法 private void OnWindowActivated(Window Window) { // 处理逻辑 } // 需要添加的引用配置: // 1. COM引用 -&gt; Microsoft Visual Basic for Applications Extensibility 5.3 // 2. .NET程序集 -&gt; Microsoft.Vbe.Interop (版本1.1.0.0) ``` **错误原因分析:** 1. 缺少正确的COM引用(Microsoft Visual Basic for Applications Extensibility 5.3) 2. 没有正确转换事件接口(需将通用Events转换为VBEEvents类型) 3. 项目目标框架版本过低(建议使用.NET Framework 4.6.1+) 4. Office PIA未正确安装(需要安装Office开发工具包) **解决方案步骤:** 1. 在解决方案资源管理器中右键点击&quot;引用&quot; -&gt; 添加COM引用 2. 勾选&quot;Microsoft Visual Basic for Applications Extensibility 5.3&quot; 3. 通过NuGet安装Microsoft.Vbe.Interop包 4. 修改项目属性 -&gt; 生成 -&gt; 取消勾选&quot;首选32位&quot; 5. 确保Office开发者工具已安装(Visual Studio Installer中勾选)
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值