1 写在前面
此文主要参考了园子里以下两篇文章:
黄聪,Microsoft Enterprise Library 5.0 系列(一) : Caching Application Block (初级)
顾磊,[EntLib]微软企业库5.0 学习之路——第四步、使用缓存提高网站的性能(EntLib Caching)
2 前面两篇博文写的很好,很全面,为何还需要本文?
大家可以点进去看下前面的文章,黄聪写的是企业库Cache的基本用法,顾磊的文章比较深入,而且自定义了CacheHelper类,实用性更强,我也抄袭了这个类(^_^ )。
我写此文的目的主要是记录下如果在项目中引入操作Cache、缓存哪些内容及最后的单元测试等~
主要是在缓存哪些数据的问题上,可能和顾磊的文章有些不同。
3 项目中引入Cache
首先从微软网站下载并安装Enterprise Library 5.0, 我这里Cache主要用在DataAccess这个项目中,是一个类库项目,所以Config的东西先不用配置,直接添加Microsoft.Practices.EnterpriseLibrary.Caching.dll的引用,
然后添加CacheHelper类,代码:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Practices.EnterpriseLibrary.Caching;
using Microsoft.Practices.EnterpriseLibrary.Caching.Expirations;
using Microsoft.Practices.EnterpriseLibrary.Common.Configuration;
using System.Reflection;
namespace DataAccess
{
public static class CacheHelper
{
private static ICacheManager cache = CacheFactory.GetCacheManager();
/// <summary>
/// Add Cache
/// </summary>
/// <param name="key"></param>
/// <param name="value"></param>
/// <param name="isRefresh">if true, should reload data every 5 mins; default value = false</param>
public static void Add(string key, object value, bool isRefresh)
{
if (isRefresh)
cache.Add(key, value, CacheItemPriority.Normal, new ATSCacheItemRefreshAction(), new AbsoluteTime(TimeSpan.FromMinutes(5)));
else
cache.Add(key, value);
}
// Summary:
// Adds new CacheItem to cache. If another item already exists with the same
// key, that item is removed before the new item is added. If any failure occurs
// during this process, the cache will not contain the item being added. Items
// added with this method will be not expire, and will have a Normal Microsoft.Practices.EnterpriseLibrary.Caching.CacheItemPriority
// priority.
//
// Parameters:
// key:
// Identifier for this CacheItem
//
// value:
// Value to be stored in cache. May be null.
//
// Exceptions:
// System.ArgumentNullException:
// Provided key is null
//
// System.ArgumentException:
// Provided key is an empty string
//
// Remarks:
// The CacheManager can be configured to use different storage mechanisms in
// which to store the CacheItems. Each of these storage mechanisms can throw
// exceptions particular to their own implementations.
public static void Add(string key, object value)
{
Add(key, value, false);
}
public static object Get(string key)
{
return cache.GetData(key);
}
public static void Remove(string key)
{
cache.Remove(key);
}
}
[Serializable]
public class ATSCacheItemRefreshAction : ICacheItemRefreshAction
{
#region ICacheItemRefreshAction Members
public void Refresh(string removedKey, object expiredValue, CacheItemRemovedReason removalReason)
{
//when expired, reload it.
if (removalReason == CacheItemRemovedReason.Expired)
{
ICacheManager c = CacheFactory.GetCacheManager();
c.Add(removedKey, expiredValue);
}
}
#endregion
}
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Practices.EnterpriseLibrary.Caching;
using Microsoft.Practices.EnterpriseLibrary.Caching.Expirations;
using Microsoft.Practices.EnterpriseLibrary.Common.Configuration;
using System.Reflection;
namespace DataAccess
{
public static class CacheHelper
{
private static ICacheManager cache = CacheFactory.GetCacheManager();
/// <summary>
/// Add Cache
/// </summary>
/// <param name="key"></param>
/// <param name="value"></param>
/// <param name="isRefresh">if true, should reload data every 5 mins; default value = false</param>
public static void Add(string key, object value, bool isRefresh)
{
if (isRefresh)
cache.Add(key, value, CacheItemPriority.Normal, new ATSCacheItemRefreshAction(), new AbsoluteTime(TimeSpan.FromMinutes(5)));
else
cache.Add(key, value);
}
// Summary:
// Adds new CacheItem to cache. If another item already exists with the same
// key, that item is removed before the new item is added. If any failure occurs
// during this process, the cache will not contain the item being added. Items
// added with this method will be not expire, and will have a Normal Microsoft.Practices.EnterpriseLibrary.Caching.CacheItemPriority
// priority.
//
// Parameters:
// key:
// Identifier for this CacheItem
//
// value:
// Value to be stored in cache. May be null.
//
// Exceptions:
// System.ArgumentNullException:
// Provided key is null
//
// System.ArgumentException:
// Provided key is an empty string
//
// Remarks:
// The CacheManager can be configured to use different storage mechanisms in
// which to store the CacheItems. Each of these storage mechanisms can throw
// exceptions particular to their own implementations.
public static void Add(string key, object value)
{
Add(key, value, false);
}
public static object Get(string key)
{
return cache.GetData(key);
}
public static void Remove(string key)
{
cache.Remove(key);
}
}
[Serializable]
public class ATSCacheItemRefreshAction : ICacheItemRefreshAction
{
#region ICacheItemRefreshAction Members
public void Refresh(string removedKey, object expiredValue, CacheItemRemovedReason removalReason)
{
//when expired, reload it.
if (removalReason == CacheItemRemovedReason.Expired)
{
ICacheManager c = CacheFactory.GetCacheManager();
c.Add(removedKey, expiredValue);
}
}
#endregion
}
4 缓存数据
在顾磊的文章中,他主要缓存一些Class,如ClassInfoService、StudentService等,代码如下:
/// <summary>
/// 通用对象反射(包含缓存)
/// </summary>
/// <param name="className">要反射的类名</param>
/// <returns></returns>
public static T CreateObject(string className)
{
var typeName = assemblyString + "." + className;
//判断对象是否被缓存,如果已经缓存则直接从缓存中读取,反之则直接反射并缓存
var obj = (T)CacheHelper.GetCache(typeName);
if (obj == null)
{
obj = (T)Assembly.Load(assemblyString).CreateInstance(typeName, true);
CacheHelper.Add(typeName, obj, true);
}
return obj;
}
public static IStudentService CreateStudent()
{
string typeName = assemblyString + ".StudentService";
if (CacheHelper.GetCache(typeName) != null)
{
return (IStudentService)CacheHelper.GetCache(typeName);
}
else
{
IStudentService service = (IStudentService)Assembly.Load(assemblyString).CreateInstance(typeName, true);
CacheHelper.Add(typeName, service, true);
return service;
}
/// 通用对象反射(包含缓存)
/// </summary>
/// <param name="className">要反射的类名</param>
/// <returns></returns>
public static T CreateObject(string className)
{
var typeName = assemblyString + "." + className;
//判断对象是否被缓存,如果已经缓存则直接从缓存中读取,反之则直接反射并缓存
var obj = (T)CacheHelper.GetCache(typeName);
if (obj == null)
{
obj = (T)Assembly.Load(assemblyString).CreateInstance(typeName, true);
CacheHelper.Add(typeName, obj, true);
}
return obj;
}
public static IStudentService CreateStudent()
{
string typeName = assemblyString + ".StudentService";
if (CacheHelper.GetCache(typeName) != null)
{
return (IStudentService)CacheHelper.GetCache(typeName);
}
else
{
IStudentService service = (IStudentService)Assembly.Load(assemblyString).CreateInstance(typeName, true);
CacheHelper.Add(typeName, service, true);
return service;
}