/// <summary> /// Gets the instance variable (either from the cache or from the specified function). /// </summary> /// <param name="key"> /// The key to use when fetching the variable. /// </param> /// <param name="replenisher"> /// The function that replenishes the cache. /// </param> /// <param name="duration"> /// The duration to cache for. /// </param> /// <param name="method"> /// Optional. The cache method to use when retrieving the value. /// </param> /// <param name="keys"> /// Optional. The keys to store/retrieve a value by. Each key combination will /// be treated as a separate cache. /// </param> /// <returns> /// The value. /// </returns> public T Get(TKey key, Func <TKey, T> replenisher, TimeSpan duration, CacheGetMethod method = CacheGetMethod.Default, params string[] keys) { var gotValue = default(bool); return(TryGet(key, replenisher, duration, default(T), out gotValue, method, keys)); }
/// <summary> /// Gets the instance variable (either from the cache or from the specified function). /// </summary> /// <param name="key"> /// The key to use when fetching the variable. /// </param> /// <param name="replenisher"> /// The function that replenishes the cache. /// </param> /// <param name="duration"> /// The duration to cache for. /// </param> /// <param name="defaultValue"> /// The value to use in the event that a value could not be retrieved (e.g., /// if the lock could not be achieved within the timeout). /// </param> /// <param name="gotValue"> /// Was the value retrieved, or was the default value used instead? /// </param> /// <param name="method"> /// Optional. The cache method to use when retrieving the value. /// </param> /// <param name="keys"> /// Optional. The keys to store/retrieve a value by. Each key combination will /// be treated as a separate cache. /// </param> /// <returns> /// The value. /// </returns> public T TryGet(TKey key, Func <TKey, T> replenisher, TimeSpan duration, T defaultValue, out bool gotValue, CacheGetMethod method = CacheGetMethod.Default, params string[] keys) { // Which cache retrieval method should be used? if (method == CacheGetMethod.FromCache) { // Get directly from cache. var lockTaken = default(bool); try { Monitor.TryEnter(InstancesLock, LockTimeout, ref lockTaken); if (lockTaken) { return(TryGetByKeys(keys, key, out gotValue)); } else { CacheSettings.FailedLockHandler(LockTimeout); gotValue = false; return(defaultValue); } } finally { if (lockTaken) { Monitor.Exit(InstancesLock); } } } else if (method == CacheGetMethod.NoCache) { // Get directly from replenisher. var returnValue = replenisher(key); gotValue = true; return(returnValue); } else { var lockTaken = default(bool); try { Monitor.TryEnter(InstancesLock, LockTimeout, ref lockTaken); if (lockTaken) { var tempInstance = default(T); var now = DateTime.Now; if (method == CacheGetMethod.Recache) { // Force the cache to replenish. tempInstance = replenisher(key); gotValue = true; UpdateValueByKeysWithoutLock(keys, key, tempInstance, now); } else { // Value already cached? var tempTuple = default(Tuple <Dictionary <string[], T>, DateTime>); if (Instances.TryGetValue(key, out tempTuple) && tempTuple.Item1.ContainsKey(keys)) { if (now.Subtract(Instances[key].Item2) >= duration) { if (method == CacheGetMethod.NoStore) { // Cache expired. Get a new value without modifying the cache. tempInstance = replenisher(key); gotValue = true; } else { // Cache expired. Replenish the cache. tempInstance = replenisher(key); gotValue = true; UpdateValueByKeysWithoutLock(keys, key, tempInstance, now); } } else { // Cache still valid. Use cached value. tempInstance = TryGetByKeys(keys, key, out gotValue); } } else { if (method == CacheGetMethod.NoStore) { // No cached value. Get a new value without modifying the cache. tempInstance = replenisher(key); gotValue = true; } else { // No cached value. Replenish the cache. tempInstance = replenisher(key); gotValue = true; UpdateValueByKeysWithoutLock(keys, key, tempInstance, now); } } } return(tempInstance); } else { CacheSettings.FailedLockHandler(LockTimeout); gotValue = false; return(defaultValue); } } finally { if (lockTaken) { Monitor.Exit(InstancesLock); } } } }
/// <summary> /// Gets the instance variable (either from the cache or from the specified function). /// </summary> /// <param name="duration"> /// The duration to cache for. /// </param> /// <param name="replenisher"> /// The function that replenishes the cache. /// </param> /// <param name="defaultValue"> /// The value to use in the event that a value could not be retrieved (e.g., /// if the lock could not be achieved within the timeout). /// </param> /// <param name="gotValue"> /// Was the value retrieved, or was the default value used instead? /// </param> /// <param name="method"> /// Optional. The cache method to use when retrieving the value. /// </param> /// <param name="keys"> /// Optional. The keys to store/retrieve a value by. Each key combination will /// be treated as a separate cache. /// </param> /// <returns> /// The value. /// </returns> public T TryGet(TimeSpan duration, Func <T> replenisher, T defaultValue, out bool gotValue, CacheGetMethod method = CacheGetMethod.Default, params string[] keys) { // Which cache retrieval method should be used? if (method == CacheGetMethod.FromCache) { // Get directly from cache. var lockTaken = default(bool); try { Monitor.TryEnter(InstanceLock, LockTimeout, ref lockTaken); if (lockTaken) { if (LastCache.HasValue) { var returnValue = TryGetByKeys(keys, out gotValue); return(returnValue); } else { gotValue = false; return(defaultValue); } } else { CacheSettings.FailedLockHandler(LockTimeout); gotValue = false; return(defaultValue); } } finally { if (lockTaken) { Monitor.Exit(InstanceLock); } } } else if (method == CacheGetMethod.NoCache) { // Get directly from replenisher. var returnValue = replenisher(); gotValue = true; return(returnValue); } else { var returnValue = defaultValue; var lockTaken = default(bool); try { Monitor.TryEnter(InstanceLock, LockTimeout, ref lockTaken); if (lockTaken) { // Variables. var now = DateTime.Now; // Force a cache update? if (method == CacheGetMethod.Recache) { UpdateValueByKeys(keys, replenisher()); } // Update cache if it's expired. else if (!LastCache.HasValue || !Instances.ContainsKey(keys) || now.Subtract(LastCache.Value) >= duration) { // Get new value? if (method == CacheGetMethod.NoStore) { returnValue = replenisher(); gotValue = true; return(returnValue); } // Update cache with new value. else { UpdateValueByKeys(keys, replenisher()); LastCache = now; } } // Return value. returnValue = TryGetByKeys(keys, out gotValue); return(returnValue); } else { CacheSettings.FailedLockHandler(LockTimeout); gotValue = false; return(defaultValue); } } finally { if (lockTaken) { Monitor.Exit(InstanceLock); } } } }