Reputation: 71
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);
}
}
}
The above cache is used by a singleton wrapper. The following is the implementation.
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);
}
}
Now my question is if I want to reload cache, can i use the following? I want to make the reload seamless, so that its OK to have threads access stale information.
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;
}
}
_internalCache is readonly. It won't let me change assignment.
Upvotes: 4
Views: 73
Reputation: 38628
Accctualy, you do not need to recreate the dictionary (given it is readonly). You could clear all values, just calling Clear()
method from IDictionary<TKey, TValue>
. For sample:
public void Reload(IDictionary<TKey, TValue> values)
{
lock (_synclock)
{
_internalCache.Clear();
foreach (var value in values)
_internalCache.Add(value);
}
}
Upvotes: 0
Reputation: 52290
The _internalCache
is read only (and I assume you don't just want to remove the readonly
keyword to make things work). But that only affects the reference to the list. You can still replace the items within the list, like this:
public void Reload(IDictionary<TKey, TValue> values)
{
lock(_synclock)
{
_internalCache.Clear();
_internalCache.AddRange(values);
}
}
Also, instead of writing all those locks yourself, perhaps you could consider using a ConcurrentDictionary which provides methods for accessing keys in a safe fashion, and even allows you to supply a delegate for repopulating an entry if a key is missing.
Upvotes: 1