首页 > 解决方案 > 我应该在课堂上的哪个位置填充 MemoryCache?

问题描述

我有一个返回缓存的类,目前的用法是:

var cache = new ProductCache().Get();

thencache是一个List<>可以枚举的。

问题是我真的应该ProductCache()在构造函数中实例化或检索它时填充这个缓存吗?

选项1:

 public class ProductCache
    {
        private readonly string key = "Product";
        private readonly object cacheLock = new object();
        ObjectCache cache = MemoryCache.Default;

        public ProductCache()
        {
        }

        public List<string> Get()
        {
            // Try to return.
            var data = cache.Get(key) as List<string>;

            if (data != null)
                return data;

            lock (cacheLock)
            {
                // Check again.
                data = cache.Get(key) as List<string>;

                if (data != null)
                    return data;

                // Populate, and return.
                data = PopulateFromElsewhere();
                cache.Set(key, data, DateTimeOffset.UtcNow.AddSeconds(20));
                return data;
            }
        }

        private List<string> PopulateFromElsewhere()
        {
            return new List<string> { "Ball", "Stick" };
        }
    }

选项 2:

public class ProductCache
{
    private readonly string key = "Product";
    private readonly object cacheLock = new object();
    ObjectCache cache = MemoryCache.Default;

    public ProductCache()
    {
        var data = cache.Get(key);

        if (data != null)
            return;

        lock (cacheLock)
        {
            // Check again.
            data = cache.Get(key);

            if (data != null)
                return;

            // Populate, and return.
            PopulateFromElsewhere();
        }
    }

    public List<string> Get()
    {
        return cache.Get(key) as List<string>;
    }

    private void PopulateFromElsewhere()
    {
        var data = new List<string> { "Ball", "Stick" };
        cache.Set(key, data, DateTimeOffset.UtcNow.AddSeconds(20));
    }
}

第二个选项线程安全(足够)吗?我觉得第一个是......

还有其他缓存..它们都很相似,所以我计划将所有实际的锁定/加载行为放在一个抽象类中

var storeCache = new StoreCache().Get();
var otherCache = new OtherCache().Get();

我猜另一个选项是一个静态类,但随后需要复制锁定机制,因为我无法使那个抽象......这可能非常好,并且像......

var cache = GlobalCache.Stores();

标签: c#memorycache

解决方案


如果您想重用缓存逻辑但希望子类具有灵活性,您可以使用模板方法模式:

public abstract class BaseCache
{
  private readonly object cacheLock = new object();
  protected ObjectCache cache = MemoryCache.Default;

  public List<string> Get()
  {
        // for example. It could be anywhere and return any type.
        ChildLogic();

        var data = cache.Get(key);

        if (data != null)
            return;

        lock (cacheLock)
        {
            // Check again.
            data = cache.Get(key);

            if (data != null)
                return;

            // Populate, and return.
            PopulateFromElsewhere();
        }
  }

  protected abstract void ChildLogic();
  protected abstract void PopulateFromElsewhere();
}

然后在您的子类中,您应该ChildLogic()PopulateFromElsewhere()任何您想要的方式实现。

当然,你根本不需要有方法ChildLogic()


推荐阅读