回到Products.aspx的代码分析,前面我的2章都分析了products.aspx这个例子里包括的三层架构学习及工厂模式的原理,接下来就是要学学NET2.0的缓存技术。
上章还留下了最后一点没有去写。就是用户控件ProductsControl.ascx.cs,先看看代码
protected void Page_Load(object sender, EventArgs e) { this.CachePolicy.Dependency = DependencyFacade.GetProductDependency(); }
解读一下 this.CachePolicy.Dependency = DependencyFacade.GetProductDependency();
一、this.CachePolicy.Dependency部份
this.CachePolicy.Dependency用帮助文件里解析为:”获取或设置与缓存的用户控件输出关联的 CacheDependency 类的实例。”这句话什么意思呢?“与缓存的用户控件输出关联的…”,返回到ProductsControl.ascx,看页面最上面有三段代码
<%@ Control Language="C#" AutoEventWireup="true" CodeFile="ProductsControl.ascx.cs" Inherits="PetShop.Web.ProductsControl" EnableViewState="false" %> <%@ Register TagPrefix="PetShopControl" Namespace="PetShop.Web" %> <%@ OutputCache Duration="100000" VaryByParam="page;categoryId" %>
原来这个用户控件ProductsControl.ascx这个控件设置了缓存
<%@ OutputCache Duration="100000" VaryByParam="page;categoryId" %>ASP.NET 页的缓存的方法是在页中使用 @ OutputCache 指令,
Duration:设置缓存到期时间,单位:秒。
VaryByParam:可用来使缓存输出因查询字符串而异,多个查询字符用分号隔开。
VaryByControl:可用来使缓存输出因控制值而异。
VaryByHeader:可用来使缓存输出因请求的 HTTP 标头而异。
VaryByCustom:可用来使缓存输出因浏览器类型或您定义的自定义字符串而异。
CacheProfile:结合配置文件使用。
Location:设置页的可缓存性,值有Any,Client,Downstream,None,Server,ServerAndClient。
这里的设置了缓存输出的参数为page及categoryID。(这里有些不明白,为什么他还要用个page?他只需要输出缓存给categoryID这个控件上就行了)
二、DependencyFacade.GetProductDependency()部份
DependencyFacade.GetProductDependency部份我们将开始分析PetShop是如何使用缓存技术的。先追踪一下DependencyFacade类,这个类放在CacheDependencyFactory项目里,根据这个项目名称我们得知,这个是专门放置缓存依赖工厂类。看来又是一个工厂模式的设计了,PetShop在看之前就听说了很了大量了工厂设计模式,看来可以好好学习了。先看这个DependencyFacade到底是在写什么东西?
DependencyFacade.cs代码:
public static class DependencyFacade { private static readonly string path = ConfigurationManager.AppSettings["CacheDependencyAssembly"]; public static AggregateCacheDependency GetCategoryDependency() { if (!string.IsNullOrEmpty(path)) return DependencyAccess.CreateCategoryDependency().GetDependency(); else return null; } public static AggregateCacheDependency GetProductDependency() { if (!string.IsNullOrEmpty(path)) return DependencyAccess.CreateProductDependency().GetDependency(); else return null; } public static AggregateCacheDependency GetItemDependency() { if (!string.IsNullOrEmpty(path)) return DependencyAccess.CreateItemDependency().GetDependency(); else return null; } }
这个类里有三个方法都有同一个返回类型为AggregateCacheDependency的东西。在这里我并不太清楚AggregateCacheDependency到底是什么东西?因为1.1原来是没有这个东西的,去看了帮助文档才知道原来这个是2.0新增的。解析为:“组合 ASP.NET 应用程序的 Cache 对象中存储的项和 CacheDependency 对象的数组之间的多个依赖项。无法继承此类。”
接下来分析一下这个类的作用,定义一个表态只读的字符串path,他的值来自配置文件,那么先看看这个配置文件里写什么东西 ?打开web.config.找到了那个配置文件为<add key="CacheDependencyAssembly" value="PetShop.TableCacheDependency"/> 他的值为PetShop.TableCacheDependency,类写了一个GetProductDependency()方法,返回值为AggregateCacheDependency的类型,如果这个path不为空,即返回一个DependencyAccess.CreateProductDependency().GetDependency().那么我们也就追踪这个类看看是什么东西?打开DependencyAccess.cs
public static class DependencyAccess { /// <summary> /// Method to create an instance of Category dependency implementation /// </summary> /// <returns>Category Dependency Implementation</returns> public static IPetShopCacheDependency CreateCategoryDependency() { return LoadInstance("Category"); } /// <summary> /// Method to create an instance of Product dependency implementation /// </summary> /// <returns>Product Dependency Implementation</returns> public static IPetShopCacheDependency CreateProductDependency() { return LoadInstance("Product"); } /// <summary> /// Method to create an instance of Item dependency implementation /// </summary> /// <returns>Item Dependency Implementation</returns> public static IPetShopCacheDependency CreateItemDependency() { return LoadInstance("Item"); } /// <summary> /// Common method to load dependency class from information provided from configuration file /// </summary> /// <param name="className">Type of dependency</param> /// <returns>Concrete Dependency Implementation instance</returns> private static IPetShopCacheDependency LoadInstance(string className) { string path = ConfigurationManager.AppSettings["CacheDependencyAssembly"]; string fullyQualifiedClass = path + "." + className; // Using the evidence given in the config file load the appropriate assembly and class return (IPetShopCacheDependency)Assembly.Load(path).CreateInstance(fullyQualifiedClass); } }
怎么没有CreateProductDependency()方法里没有GetDependency()这个方法呢?怎么办。继续分析这个DependencyAccess.cs类。CreateProductDependency()代码如下:
public static IPetShopCacheDependency CreateProductDependency() { return LoadInstance("Product"); }
返回一个类型为IPetShopCacheDependency类型的东西,这个东西就是LoadInstance("Product")这个方法,代码如下:
private static IPetShopCacheDependency LoadInstance(string className) { string path = ConfigurationManager.AppSettings["CacheDependencyAssembly"]; string fullyQualifiedClass = path + "." + className; return (IPetShopCacheDependency)Assembly.Load(path).CreateInstance(fullyQualifiedClass); }
这里用到反射,由上至下我们就可以知道这个是返回一个” PetShop.TableCacheDependency.Product”。
那么我们再将思路跳转到TableCacheDependency项目里的Product.cs
public class Product : TableDependency { /// <summary> /// Call its base constructor by passing its specific configuration key /// </summary> public Product() : base("ProductTableDependency") { } }
这个类继承了TahleDependency,调用基类构造函数。那也就要转到基类去看看罗。TableDependency所以的项目文件为TableCacheDependency/ TableDependency.cs,代码如下:
public abstract class TableDependency : PetShop.ICacheDependency.IPetShopCacheDependency { // This is the separator that's used in web.config protected char[] configurationSeparator = new char[] { ',' }; protected AggregateCacheDependency dependency = new AggregateCacheDependency(); /// <summary> /// The constructor retrieves all related configuration and add CacheDependency object accordingly /// </summary> /// <param name="configKey">Configuration key for specific derived class implementation</param> protected TableDependency(string configKey) { string dbName = ConfigurationManager.AppSettings["CacheDatabaseName"]; string tableConfig = ConfigurationManager.AppSettings[configKey]; string[] tables = tableConfig.Split(configurationSeparator); foreach (string tableName in tables) dependency.Add(new SqlCacheDependency(dbName, tableName)); } public AggregateCacheDependency GetDependency() { return dependency; } }
这个类也是继承了接口PetShop.ICacheDependency.IPetShopCacheDependency,那么,这个TableDependency(string configKey)这个方法有什么用呢。看看源代码:定义字符串dbName,由配置文件里得到这个值为“MSPetShop4”,
这里有个疑问就是定义configurationSeparator怎么是这char类型的数组。这里定义数组有什么作用?怎么就不直接使用char?
这里是将传进来的字符串变成转成AggregateCacheDependency类型的一个集合.使用GetDependency()返回这一类型。那么我们看Product.cs页 public Product() : base("ProductTableDependency") { }
这样我们实例化product之后.使用GetDependency()方法就能获取AggregateCacheDependency类型的值了,这个值就是使用foreach循环用dependency将一个一个值组合起来。而使用base("ProductTableDependency")我们就可以知道放在TableDependency()这里的string 传入为”ProductTableDependency”,那我们直接套进去那值,就可以得到tableConfig的值为"Product,Category"。那么dependencyY就是添加了2个SqlCacheDependency,分别为(“Product”,”MSPetShop4”)及(“Category”,”MSPetShop4”),最终结果只是返回这两个东西合成的一个结果集。
返回后那么缓存依赖this.CachePolicy.Dependency = DependencyFacade.GetProductDependency();我并不知道这里加了个缓存依赖有什么作用?好像这整个页面里没有缓存的设置
本文来自CSDN博客,转载请标明出处:http://blog.csdn.net/clongge/archive/2008/08/18/2790239.aspx