如何在c#中实现通用缓存管理器

时间:2012-11-22 21:43:15

标签: c# generics locking

我正在尝试实现通用缓存管理器,但是我不确定如何进行锁定。

到目前为止我有以下内容,但是如果我有两个具有相同返回类型的缓存条目,那么我猜测将使用相同的锁定对象!

public class CacheManager : ICacheManager
{
    static class TypeLock<T>
    {
        public static readonly object SyncLock = new object();
    }
    private readonly ICache _cache;
    public CacheManager(ICache cache)
    {
        if (cache == null)
            throw new ArgumentNullException("cache");

        _cache = cache;
    }

    public TResult AddCache<TResult>(string cacheKey, Func<TResult> acquire, int cacheDurationInMinutes) where TResult : class
    {
        return AddCache(cacheKey, null, acquire, cacheDurationInMinutes);
    }

    public TResult AddCache<TResult>(string cacheKey, CacheDependency dependency, Func<TResult> acquire, int cacheDurationInMinutes) where TResult : class
    {
        var entry = acquire.Invoke();
        if (entry != null)
        {
            if (dependency != null)
                _cache.InsertWithDependency(cacheKey, entry, dependency, DateTime.Now.AddMinutes(cacheDurationInMinutes));
            else
                _cache.Insert(cacheKey, entry, DateTime.Now.AddMinutes(cacheDurationInMinutes));
        }
        return entry;
    }

    public TResult GetOrAddCache<TResult>(string cacheKey, Func<TResult> acquire, int cacheDurationInMinutes) where TResult : class
    {
        return GetOrAddCache(cacheKey, null, acquire, cacheDurationInMinutes);
    }

    public TResult GetOrAddCache<TResult>(string cacheKey, CacheDependency dependency, Func<TResult> acquire, int cacheDurationInMinutes) where TResult : class
    {
        var entry = _cache.GetItem(cacheKey) as TResult;

        if (entry == null)
        {
            lock (TypeLock<TResult>.SyncLock)
            {
                entry = _cache.GetItem(cacheKey) as TResult;
                if (entry == null)
                {
                    entry = acquire.Invoke();
                    if (entry != null)
                    {
                        if (dependency != null)
                            _cache.InsertWithDependency(cacheKey, entry, dependency,
                                                        DateTime.Now.AddMinutes(cacheDurationInMinutes));
                        else
                            _cache.Insert(cacheKey, entry, DateTime.Now.AddMinutes(cacheDurationInMinutes));
                    }
                }
            }
        }

        return entry;
    }
}

非常感谢任何帮助!

3 个答案:

答案 0 :(得分:1)

你是对的,这会对同一类型的所有缓存条目使用相同的锁。为了保持独立于此缓存管理器的实际缓存方法(内存,文件,数据库...),我建议为每个缓存条目存储一个额外的同步对象,因此您的缓存条目将查找例如Tuple<object, TResult>而不是TResult只需object,其中new object()对于每个条目都是{{1}},并将用于锁定。

答案 1 :(得分:1)

除非真的需要,否则你永远不应该锁定你的缓存代码。 如果您不想使用任何众所周知的缓存,请使用Concurrent字典。

我还说你可能应该使用System.Runtime.MemorCache代替。

或者您使用的解决方案可以为您抽象, 比如我的CacheManager https://github.com/MichaCo/CacheManager;)

答案 2 :(得分:0)

我不确定你应该使用lock,alos,为什么不使用MemoryCache而不是ICache接口?内存缓存不够通用吗? 为什么强制缓存时间是分钟,你应该将时间跨度传递给缓存方法,我会更通用。

几个月前我实施了a version of a cache manager,但它是面向网络的。