petshop学习笔记(4)

来源:互联网 发布:上海一条网络 编辑:程序博客网 时间:2024/06/06 01:00

回到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();我并不知道这里加了个缓存依赖有什么作用?好像这整个页面里没有缓存的设置

原创粉丝点击