C#重载单例缓存

时间:2011-12-06 17:02:28

标签: c# .net caching singleton

我需要一些指示。 我有以下键/值缓存:

public class Cache<TKey, TValue> : ICache<TKey, TValue>
{
    private readonly IDictionary<TKey, TValue> _internalCache;
    private readonly object _syncLock = new object();

    public Cache()
    {
        _internalCache = new Dictionary<TKey, TValue>();
    }

    public TValue this[TKey key]
    {
        get
        {
            lock (_syncLock) {
               //...
            }
        }
        set
        {
            lock (_syncLock) {
               //...
            }
        }
    }

    public ICollection<TValue> GetAll()
    {
        lock (_syncLock) {
            return _internalCache.Values;
        }
    }

    public bool ContainsKey(TKey key)
    {
        lock (_syncLock)
        {
            return _internalCache.ContainsKey(key);
        }
    }

}   

上面的缓存由单身包装器使用:

 public class ActivityCache : ICache<string, Activity> 
 {
    private readonly ICache<string, Activity> _cache = new Cache<string, Activity>();

    private static readonly ActivityCache _instance = new ActivityCache();

    // http://www.yoda.arachsys.com/csharp/singleton.html
    static ActivityCache()
    {
    }

    ActivityCache()
    {
    }

    public static ActivityCache Instance
    {
        get { return _instance; }
    }

    public Activity this[string activityUrl]
    {
        get
        {
            if (string.IsNullOrEmpty(activityUrl))
            {
                return null;
            }

            return _cache[activityUrl];
        }
        set
        {
            if (string.IsNullOrEmpty(activityUrl))
            {
                return;
            }

            _cache[activityUrl] = value;
        }
    }

    public ICollection<Activity> GetAll()
    {
        return _cache.GetAll();
    }

    public bool ContainsKey(string key)
    {
        return _cache.ContainsKey(key);
    }
}

这工作正常(我没有注意到/听说过任何错误......):)。

但现在我遇到了问题。我需要使用新的键/值重新加载缓存。

问题1。)我可以实现重新加载缓存的“安全”重载方法(Cache类中的Dictionary)吗?

E.g:

    public void Reload(IDictionary<TKey, TValue> values)
    {
        lock (_syncLock)
        {
            _internalCache.Clear();
            foreach (KeyValuePair<TKey, TValue> value in values)
            {

                /* Problems can (will) occur if another 
                   thread is calling the GetAll method... */
                _internalCache[value.Key] = value.Value;
            }
        }
    }

问题2。)我应该使用一些IoC容器还是其他库?

谢谢!

注意:我正在使用.NET 3.5

2 个答案:

答案 0 :(得分:2)

使用ConcurrentDictionary,那么你就不必处理同步了。

此外,您也不想重新加载所有缓存项目。相反,你想要做错,按需加载键/值存储中的缓存对象。

您可以使用时间戳或某些版本控制。如果你为每个键/值对重新加载数据,那么你就不必锁定整个集合。

我真的建议你使用ConcurrentDictionary。

答案 1 :(得分:1)

你也应该锁定GetAll。

你可以使用双缓冲类型技术来减轻重载:

public void Reload(IDictionary<TKey, TValue> values)
{
    cache = new Dictionary<TKey, TValue> ();
    foreach (KeyValuePair<TKey, TValue> value in values)
    {
        cache[value.Key] = value.Value;
    }

    lock (_syncLock)
    {
        _internalCache = cache;
    }
}

如果您在调用重新加载时不介意读者可能会访问可能过时的信息,这将有效。