首页 > 编程 > .NET > 正文

.NET 缓存模块设计实践

2024-07-10 12:46:53
字体:
来源:转载
供稿:网友

上一篇谈了我对缓存的概念,框架上的理解和看法,这篇承接上篇讲讲我自己的缓存模块设计实践。 

基本的缓存模块设计
最基础的缓存模块一定有一个统一的CacheHelper,如下: 

  public interface ICacheHelper  {       T Get<T>(string key);            void Set<T>(string key, T value);       void Remove(string key);          }

然后业务层是这样调用的 

  public User Get(int id)    {      if (id <= 0)        throw new ArgumentNullException("id");      var key = string.Format(USER_CACHE_KEY, id);      var user = _cacheHelper.Get<User>(key);      if (user != null)        return user;      return _repository.Get(id);    }  

上面的代码没什么错误,但是实际运用的时候就产生疑问了,因为我一直强调缓存要保存"热数据",那样"热数据"一定会有过期的时候,我们不可能另外写一个去Set。所以干脆就结合到一起写是比较合适的。 

public User GetV2(int id){  if (id <= 0)    throw new ArgumentNullException("id");  var key = string.Format(USER_CACHE_KEY, id);  var user = _cacheHelper.Get<User>(key);  if (user != null)    return user;    user = _repository.Get(id);  if (user != null)    _cacheHelper.Set(key, user);    return user;}

上面的代码其实只是加了一个Set而已,就这样的设计的话,每次一个Get需要的重复代码实在是太多了,那么是不是应该更精简?这时候吃点C#语法糖就很有必要了,语法糖偶尔吃点增进效率,何乐而不为? 

public User GetV3(int id){   if (id <= 0)     throw new ArgumentNullException("id");   var key = string.Format(USER_CACHE_KEY, id);    return _cacheHelperV2.Get<User>(key, () => _repository.Get(id));      }//ICache Get<T>实现public T Get<T>(string key, Func<T> fetch = null){  T result = default(T);  var obj = Cache.Get(key);  if (obj is T)  {    result = (T)obj;  }  if(result == null)  {    result = fetch();    if (result != null)      Set(key, result);  }  return result;}      

这里我直接把Set方法都包装进了ICache.Get<T>,附带上Fetch Func。这样就把公共的操作抽象到了一起,简化了Cache的调用,完美的符合了我的想法。

缓存模块设计进阶
上一节里的ICache V3几乎已经最精简了,但是其实参考了ServiceStack.Redis之后,我发现了更加的抽象方式。很明显上一节的所有代码里,都是手动管理Key的,对于通常的对象Cache,这个Key还需要手动吗?来上最后一份改进。 

public T Get<T>(object id, Func<T> fetch = null){  var type = typeof(T);  var key = string.Format("urn:{1}:{2}", type.Name, id.ToString());//这里是关键,直接用TypeName来充当Key  return Get(key, fetch);}public T Get<T>(string key, Func<T> fetch = null){  T result = default(T);  var obj = Cache.Get(key);  if (obj is T)  {    result = (T)obj;  }  if (result == null)  {    result = fetch();    if (result != null)      Set(key, result);   }   return result;}            
发表评论 共有条评论
用户名: 密码:
验证码: 匿名发表