首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >内存缓存服务

内存缓存服务
EN

Code Review用户
提问于 2014-10-23 06:35:54
回答 1查看 1.8K关注 0票数 1

我在很多地方重复这个代码:

代码语言:javascript
复制
public class ProductTypeService : IProductTypeService
{
    public async Task<IList<ProductType>> GetAllAsync(int sectionId = -1)
    {
        string key = "ProductTypeService_" + "GetAllAsync" + sectionId;
        var list = _memoryCacheService.Get<IList<ProductType>>(key);
        if (list == null)
        {
            list = await _repository.GetAllAsync(sectionId);
            _memoryCacheService.Save(key, list);
        }
        return list;
    }

public class VendorService : IVendorService
{
    public async Task<IList<Vendor>> GetAllAsync()
    {
        string key = "VendorService_" + "GetAllAsync";
        var list = _memoryCacheService.Get<IList<Vendor>>(key);
        if (list == null)
        {
            list = await _repository.GetAllAsync();
            _memoryCacheService.Save(key, list);
        }
        return list;
    }

关键是类+方法+参数的组合。唯一的改变是_repository.XX(XX, XX, ...........)。我怎么才能把它弄干?

EN

回答 1

Code Review用户

发布于 2014-10-23 09:39:18

--我们先不复习:

  • ProductType
  • 供应商
  • IProductTypeService (只是一点点)
  • IVendorService
  • IRepository (只是一点点)
  • _memorxCahceService是什么?我将使用ObjectCache。

我们需要讨论什么?

包含通用方法和实现的通用服务实现。

BaseService

我们将需要一个类,它可以成为到存储库和缓存的桥梁,因此可以定义它为BaseService。这意味着我们将以一种通用的方式在不同的repository+cache组合中使用它。这里没有黑魔法,继续前进。

首先,我们需要从问题中的两个服务实现中提取常见的内容:

  • 获取缓存密钥
  • 尝试从缓存中加载数据
代码语言:javascript
复制
public abstract class BaseService<T>
{
    private ObjectCache ObjectCache { get; set; }
    private IRepository<T> Repository { get; set; }

    protected BaseService(IRepository<T> repository)
        : this(MemoryCache.Default, repository)
    {
    }

    protected BaseService(ObjectCache objectCache, IRepository<T> repository)
    {
        ObjectCache = objectCache;
        Repository = repository;
    }

    protected virtual string GetCacheKey(string suffix, int sectionId = -1)
    {
        return GetType().Name + "_" + suffix + sectionId;
    }

    protected virtual async Task<ICollection<T>> GetAllAsyncValueFactory()
    {
        return await Repository.GetAllAsync();
    }

    public virtual async Task<ICollection<T>> GetAllAsync(int sectionId = -1)
    {
        var key = GetCacheKey("GetAllAsync", sectionId);

        var list = ObjectCache.Get(key) as ICollection<T>;

        if (list == null)
        {
            return ObjectCache.AddOrGetExisting(key, await GetAllAsyncValueFactory(), new CacheItemPolicy
            {
                //TODO: define cache policy
            }) as ICollection<T>;
        }

        return list;
    }
    }

这里我们要做的是在构造函数中定义我们需要的东西:存储库和ObjectCache,但是如果没有其他任何东西,我们可以使用默认的MemoryCache实例。

主要是我提取了代码中通常使用的所有逻辑,但是使用了通用实现(提示:不要使用IList是一个脏接口)。每个方法都是虚拟的,因此可以在派生类中轻松地重写它们,您可以定义不同的缓存键,或者可以告诉您如何从当前存储库获取数据。

接口实现

因为泛型基类,所以我们只需要在接口实现类中定义构造函数,因为您可以这样做:

代码语言:javascript
复制
public class ProductTypeService : BaseService<ProductType>, IProductTypeService
{
    public ProductTypeService(ObjectCache objectCache, IRepository<ProductType> repository)
        : base(objectCache, repository)
    {
    }

    public ProductTypeService(IRepository<ProductType> repository)
        : base(repository)
    {
    }
}

构造函数实现将根据您未知的需求而有所不同。

票数 2
EN
页面原文内容由Code Review提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://codereview.stackexchange.com/questions/67655

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档