System.Web.PreApplicationStartMethodAttribute应用场景

前几天整理了一下开发框架的内容,记录一下我们的项目中,对 System.Web.PreApplicationStartMethodAttribute这个特性的应用场景:

首先,介绍一下这个属性,参考:https://haacked.com/archive/2010/05/16/three-hidden-extensibility-gems-in-asp-net-4.aspx/
这个特性是Asp.net4新增的一个功能,可以让你的代码在站点的Application_Start方法之前运行,可以方便的注入或进行一些初始化工作,而不需要在每个项目去重复写这些代码。

以下是应用场景:
一、对线上运行中的项目,希望统一配置HttpWebRequest的UserAgent,并添加一些诊断信息和链路信息,
同时把请求的头、请求Body和响应的头和Body数据完整记录日志。
如果按常规作法,一般是封装一个dll类库,要求所有成员,使用这个类库里封装的方法,但是对旧项目,需要进行改造,有些新成员的新项目也可能忘记引用这个类库,或者引用了,但是没有使用它。
我们的作法,封装一个类库,加上PreApplicationStartMethodAttribute属性,然后编译成dll,在Jenkins推送线上站点时,把这个dll也推送到站点的bin目录下,整个过程对业务项目是透明的,RD们只需要按自己的做法去开发和部署即可。
实现步骤:
1、新建一个类库,打开项目的Properties/AssemblyInfo.cs,在里面添加一行代码:

[assembly: PreApplicationStartMethod(typeof(CustomWebRequest), "Patch")]

2、完成方法 CustomWebRequest.Patch() 的实现,对HttpWebRequest进行扩展实现,并增加2个Filter:
UserAgentFilter 和 NLogFilter,实现UserAgent的统一和请求日志的输出。

这整个类库的整体实现和测试代码,我扔到Github上了:
https://github.com/youbl/DemoCode/tree/master/src/Library/Beinet.Request

可以下载这个项目,编译后,随便扔到你的某个站点bin目录下,可以看到有日志输出,并且UserAgent也变了。

二、接入Pinpont,实现项目的整个请求链路跟踪、Sql执行情况记录、Redis访问情况记录等;
三、接入注册服务发现,启动时进行服务注册,退出时进行服务卸载。


注:Nuget上有个WebActivatorEx库,它也定义了相同的一个类:PreApplicationStartMethodAttribute,简单来说:WebActivatorEx.PreApplicationStartMethodAttribute 和 System.Web.PreApplicationStartMethodAttribute 实现的功能是一样的,通过反编译WebActivatorEx组件的源码,可以看到有如下定义:

[assembly: System.Web.PreApplicationStartMethod(typeof (ActivationManager), "Run")]

说明 WebActivatorEx 也是基于System.Web.PreApplicationStartMethodAttribute实现,但是:
1、WebActivatorEx.PreApplicationStartMethodAttribute 支持 Order属性,可以指定多个方法的执行顺序:

[assembly: WebActivatorEx.PreApplicationStartMethod(typeof(Starter), "Start", Order = 12)]

2、WebActivatorEx 支持额外的2个属性:
WebActivatorEx.PostApplicationStartMethodAttribute
WebActivatorEx.ApplicationShutdownMethodAttribute

// 在Application_Start运行结束后执行这个方法: Starter.End()
[assembly: WebActivatorEx.PostApplicationStartMethod(typeof(Starter), "End", Order = 12)]
// 在应用程序退出时执行这个方法: Starter.Quit()
[assembly: WebActivatorEx.ApplicationShutdownMethod(typeof(Starter), "Quit", Order = 12)]

通过ActivationManager.Run()方法的源码可以看到,这2个属性是通过注册一个IHttpModule来实现,
在Module的Init里调用PostApplicationStartMethod,
在Module的Dispose里调用ApplicationShutdownMethod:

if (HostingEnvironment.IsHosted)
{
    Type moduleType = typeof (ActivationManager.StartMethodCallingModule);
    if (flag)
        (WebConfigurationManager.GetWebApplicationSection("system.web/httpModules") as HttpModulesSection).
                        Modules.Add(new HttpModuleAction(moduleType.FullName, moduleType.AssemblyQualifiedName));
    else
        DynamicModuleUtility.RegisterModule(moduleType);
}


private class StartMethodCallingModule : IHttpModule
{
    private static object _lock = new object();
    private static int _initializedModuleCount;

    public void Init(HttpApplication context)
    {
    lock (ActivationManager.StartMethodCallingModule._lock)
    {
        if (ActivationManager.StartMethodCallingModule._initializedModuleCount++ != 0)
        return;
        ActivationManager.RunPostStartMethods();
    }
    }

    public void Dispose()
    {
    lock (ActivationManager.StartMethodCallingModule._lock)
    {
        if (--ActivationManager.StartMethodCallingModule._initializedModuleCount != 0)
        return;
        ActivationManager.RunShutdownMethods();
    }
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

游北亮

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值