从HttpApplication派生的Global 类有很多用处包括管理应用程序状态和请求状态 Visual StudioNET 创建的globalasax文件为每个web 应用程序生成一个从HttpApplication类派成的Global类这个类包含很多事件处理程序例如Application_Start和 Session_Start 或许有人认为每个web应用程序只有一个Global类的实例事实上在大多数应用程序框架中代表Application的对象都是singleton – 就是说只有一个实例存在我们也知道ASPNET运行时只有在应用程序开始的时候才调用Application_Start事件处理方法所有这些好像都在暗示在我们的ASPNET Web应用程序中只有一个Global对象的实例但是所有这些确确实实是误导! ASPNET 运行时(ASPNET runtime以下简称运行时)维护了一个HttpApplication对象池当一个请求进来的时候运行时从该池中取出一个HttpApplication对象来服务于当前请求该HttpApplication对象一直和该请求相关联且只和该请求相关联直到请求被处理完毕当请求完成后运行时把该对象归还到池中稍后会从池中再次取出去服务于另外的请求但一个请求每次只能和某一个HttpApplication对象相关联 Application State VS Request State Application对象(HttpApplicationState 类型译者按Application对象是HttpApplication类的一个属性是web应用程序全局唯一的web应用程序第一次有请求进来的时候创建的) 是我们在web应用程序内保存全局信息的地方Application对象是一个很方便的保存全局信息的地方例如保存数据库的连接字符串 private void Page_Load(object sender SystemEventArgs e) { string connectionString = Application[ConnectionString]ToString(); } 你也可以在HttpApplication类中声明静态成员变量来保存应用程序状态信息例如上例中的数据库连接字符串可以用如下方式保存 public class Global : SystemWebHttpApplication { public static readonly string ConnectionString = connection information; } 可以在ASPNET代码的任何地方访问该静态成员变量例如:string connectionString = GlobalConnectionString; 非常重要的一点是如果你想让该字符串可以全局范围内被访问到则该字符串必须声明为静态成员变量(你也可以创建一个静态的属性) 相反如果你在Global类型使用一般成员变量(非静态)则只能用来保存请求状态举个例子来说明下面的代码将在调试窗口中输出所有请求的处理时间(毫秒) public class Global : SystemWebHttpApplication { protected DateTime beginRequestTime; protected void Application_BeginRequest(Object sender EventArgs e) { beginRequestTime = DateTimeNow; } protected void Application_EndRequest(Object sender EventArgs e) { string messageFormat = Elapsed request time (ms) = {}; TimeSpan diffTime = DateTimeNow beginRequestTime; TraceWriteLine( StringFormat(messageFormat diffTimeTotalMilliseconds ) ); } } 好现在让我们回到上面关于保存应用程序状态的话题那个方法更好的呢在Application对象中保存对象的引用还是在Global类中声明静态成员或属性?各种方式各有优劣在Global类中保存全局静态成员可以使你的数据访问具有强类型不象Application对象你不需要进行类型转换下面的代码说明了它们的区别 DataSet cachedData = (DataSet)Application[MyDataSet]; string myString = Application[MyString]ToString(); DataSet cachedData = GlobalMyDataSet; string myString = GlobalMyString; 强类型使你的的代码更加清晰和强壮在应用程序性能要求比较高的情况下这种方式可以避免运行时类型转换带来的性能损失如果你保存的是值类型的数据强类型还可以避免装箱(boxing)和卸箱(unboxing)所带来的性能损失另外Application对象还有因为线程同步造成的锁定所带来的性能上问题如果你的全局数据只初始化一次再也不会改变使用Global类中的静态成员可以避免锁定带来的性能损失但如果你采用了这种方式强烈推荐你使用访问器(属性)以保证该变量是只读的如果你既要读又要写在Global类中的静态成员变量记住要保证线程安全Application对象通过获取读写锁已经内在的提供了线程安全保证 比较安全的初始化全局静态成员变量的地方是在Application_Start事件处理程序中即使全局范围有很多个Global对象的实例运行时只会在Global对象第一次创建的时候调用Application_Start事件处理程序 比较理想的初始化请求状态变量的地方是Application_BeginRequest请求状态变量一般情况下不需要线程安全因为每个Global对象在同一时刻只服务于一个请求 |