最近有时间看一些.net的框架代码,发现一个有意思的问题,就是HttpModule中的
Init函数下的事件绑定,因为事件的绑定在事件发生后相应的处理委托即为null,但
下面的代码(功能:地址的重定向)为什么只是绑定一次后就能在每个WEB请求过来
时都能运行ReUrl_BeginRequest事件呢。
public class HttpModule : System.Web.IHttpModule
{
public void Init(HttpApplication context)
{
context.BeginRequest += new EventHandler(ReUrl_BeginRequest);
....
}
private void ReUrl_BeginRequest(object sender, EventArgs e)
{
....
}
最近有时间看一些.net的框架代码,发现一个有意思的问题,就是HttpModule中的Init函数下的事件绑定,因为事件
的绑定在事件发生后相应的处理委托即为null,但下面的代码(功能:地址的重定向)为什么只是绑定一次后就能在每个
WEB请求过来时都能运行
ReUrl_BeginRequest事件呢。
public class HttpModule : System.Web.IHttpModule
{
public void Init(HttpApplication context)
{
context.BeginRequest += new EventHandler(ReUrl_BeginRequest);
....
}
private void ReUrl_BeginRequest(object sender, EventArgs e)
{
....
}
原因主要是出现System.Web.HttpApplication 中的这个函数HookupEventHandlersForAppplicationAndModules这个函
数(如下)

private void HookupEventHandlersForAppplicationAndModules(MethodInfo[] handlers)


{
for (int num1 = 0; num1 < handlers.Length; num1++)

{
MethodInfo info1 = handlers[num1];
string text1 = info1.Name;
int num2 = text1.IndexOf('_');
string text2 = text1.Substring(0, num2);
object obj1 = null;
if (string.Compare(text2, "Application", true, CultureInfo.InvariantCulture) == 0)

{
obj1 = this;
}
else if (this._moduleCollection != null)

{
obj1 = this._moduleCollection[text2];
}
if (obj1 != null)

{
Type type1 = obj1.GetType();
EventDescriptorCollection collection1 = TypeDescriptor.GetEvents(type1);
string text3 = text1.Substring(num2 + 1);
EventDescriptor descriptor1 = collection1.Find(text3, true);
if ((descriptor1 == null) && (string.Compare(text3.Substring(0, 2), "on", true, CultureInfo.InvariantCulture) == 0))

{
text3 = text3.Substring(2);
descriptor1 = collection1.Find(text3, true);
}
MethodInfo info2 = null;
if (descriptor1 != null)

{
EventInfo info3 = type1.GetEvent(descriptor1.Name);
if (info3 != null)

{
info2 = info3.GetAddMethod();
}
}
if (info2 != null)

{
ParameterInfo[] infoArray1 = info2.GetParameters();
if (infoArray1.Length == 1)

{
Delegate delegate1 = null;
ParameterInfo[] infoArray2 = info1.GetParameters();
if (infoArray2.Length == 0)

{
if (infoArray1[0].ParameterType != typeof(EventHandler))

{
goto Label_0168;
}
ArglessEventHandlerProxy proxy1 = new ArglessEventHandlerProxy(this, info1);
delegate1 = proxy1.Handler;
}
else

{
try

{
delegate1 = Delegate.CreateDelegate(infoArray1[0].ParameterType, this, text1);
}
catch (Exception)

{
goto Label_0168;
}
}
try

{

info2.Invoke(obj1, new object[]
{ delegate1 });
}
catch (Exception)

{
}
Label_0168:;
}
}
}
}
}




请注意_moduleCollection这个属性,它其实可以理解为一系列的HttpModule的集合,里面的数据主要是我们在web.config
中的内容,如下:
<httpModules>
<add type="Discuz.Forum.HttpModule, Discuz.Forum" name="HttpModule" />
</httpModules>
上面的代码基本上是找出相关的HTTPMODULE或HANDLER中的绑定事件,然后去运行。
那是什么函数实现了将web.config中的设置获取到_moduleCollection变量中呢,InitModules()这个函数不名思议就是干
这个活的,它的代码如下
private void InitModules()


{
HttpModulesConfiguration configuration1 = (HttpModulesConfiguration) HttpContext.GetAppConfig("system.web/httpModules");
if (configuration1 == null)

{
throw new HttpException(HttpRuntime.FormatResourceString("Missing_modules_config"));
}
this._moduleCollection = configuration1.CreateModules();
int num1 = this._moduleCollection.Count;
for (int num2 = 0; num2 < num1; num2++)

{
this._moduleCollection[num2].Init(this);
}
GlobalizationConfig config1 = (GlobalizationConfig) HttpContext.GetAppConfig("system.web/globalization");
if (config1 != null)

{
this._appLevelCulture = config1.Culture;
this._appLevelUICulture = config1.UICulture;
}
}

另外它还运行了Init方法,而这个方法所干的活就是我们在实现IHTTPMODULE中所希望的操作即:
{
context.BeginRequest += new EventHandler(ReUrl_BeginRequest);
.....
}
这样当外部请求来时,系统会运行到System.Web.HttpApplication.InitInternal函数,它会去调用
HookupEventHandlersForAppplicationAndModules,
这样就能在只绑定一次事件之后,即使有新的请求到来是时,系统依然知道要去运行那些要处理的事件。
这篇文章没有什么技术含量,因为很长时间没写东西了,所以发了出来, 希望大家见谅,献丑了。
参考文章:http://www.cnblogs.com/dudu/archive/2006/01/14/317016.html
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 开发者必知的日志记录最佳实践
· SQL Server 2025 AI相关能力初探
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 园子的第一款AI主题卫衣上架——"HELLO! HOW CAN I ASSIST YOU TODAY
· 【自荐】一款简洁、开源的在线白板工具 Drawnix