/// <summary> /// Retrieve the delegate implementing object renewal logic for a given unique key. /// </summary> /// <param name="key">Unique identificator.</param> /// <returns>Returns the instance, if failed null.</returns> /// <exception cref="ArgumentNullException">thrown, if <paramref name="key"/> is null.</exception> public Func <object> GetRenewalLogic(string key) { if (key == null) { throw new ArgumentNullException("key"); } CacheRegistryLogic logic = null; _lock.EnterReadLock(); try { if (!_logicCache.TryGetValue(key, out logic)) { logic = null; } } catch { } finally { _lock.ExitReadLock(); } return((logic == null) ? null : logic.ObjectRenewalLogic); }
/// <summary> /// Retrieve the object under the given unique key value. /// If the entry instance has already expired, it will re-create it form the object renewal logic. /// The method is not optimised for cases when executing the re-creation logic will result with null. /// </summary> /// <param name="key">Unique identificator.</param> /// <returns>Returns the instance, if failed null.</returns> /// <exception cref="ArgumentNullException">thrown, if <paramref name="key"/> is null.</exception> public object GetObject(string key) { if (key == null) { throw new ArgumentNullException("key"); } CacheRegistryLogic logic = null; object item = null; _lock.EnterReadLock(); try { if (_logicCache.TryGetValue(key, out logic)) { logic.Lock.EnterReadLock(); // entry, read lock try { item = _objectCache.Get(key); } catch { } finally { logic.Lock.ExitReadLock(); // entry, read unlock } } } catch { } finally { _lock.ExitReadLock(); } if (logic == null) { return(null); } return((item != null) ? item : ForceRenewal(key)); }
/// <summary> /// Add entry to cache registry. /// </summary> /// <param name="key">Unique identificator.</param> /// <param name="expiration">Expiration period for each instance of an entry.</param> /// <param name="objectRenewalLogic"> /// The delegate used to create the object after each expiration. /// If delegate execution results with null, a <typeparamref name="ArgumentException"/> will be thrown. /// </param> /// <param name="createOnAdd"> /// Flag determining if the instance should be created upon registration. Default value: true /// </param> /// <returns>true, if the registration and optional instance creation succeeded.</returns> /// <exception cref="ArgumentNullException"> /// thrown, if <paramref name="objectRenewalLogic"/> or <paramref name="key"/> is null. /// </exception> /// <exception cref="ArgumentException"> /// thrown, if <paramref name="expiration"/> period is negative or <paramref name="objectRenewalLogic"/> delegate execution results with null. /// </exception> public bool Add(string key, TimeSpan expiration, Func <object> objectRenewalLogic, bool createOnAdd = true) { if (key == null) { throw new ArgumentNullException("key"); } CacheRegistryLogic logic = CacheRegistryLogic.Create(expiration, objectRenewalLogic); // throws bool shouldThrow = false; bool result = false; _lock.EnterReadLock(); try { result = _logicCache.ContainsKey(key); } catch { } finally { _lock.ExitReadLock(); } if (result == true) { return(false); } _lock.EnterUpgradeableReadLock(); try { if (!_logicCache.ContainsKey(key)) { _lock.EnterWriteLock(); // registry, write lock try { if (createOnAdd) { object item = logic.ObjectRenewalLogic(); if (item == null) { shouldThrow = true; } else { System.Runtime.Caching.CacheItemPolicy cacheItemPolicy = new System.Runtime.Caching.CacheItemPolicy() { AbsoluteExpiration = DateTimeOffset.UtcNow.Add(logic.Expiration), }; _objectCache.Set(key, item, cacheItemPolicy); _logicCache.Add(key, logic); } } else { _logicCache.Add(key, logic); } result = true; } catch { } finally { _lock.ExitWriteLock(); // registry, write unlock } } } catch { } finally { _lock.ExitUpgradeableReadLock(); } if (shouldThrow) { throw new ArgumentException("objectRenewalLogic"); } return(result); }