/// <summary> /// Remove item from cache by key. /// </summary> /// <param name="key">The key.</param> /// <param name="raiseEvents">Indicates whether events should be raised.</param> /// <param name="action">The action that need to be executed in synchronization with the item cache removal.</param> /// <returns>The value indicating whether the item was removed.</returns> private bool RemoveItem(TKey key, bool raiseEvents, Action action = null) { // Try to get item, if there is no item by that key then return true to indicate that item was removed. var item = default(CacheStorageValueInfo <TValue>); if (!_dictionary.TryGetValue(key, out item)) { return(true); } action?.Invoke(); var cancel = false; var expirationPolicy = item.ExpirationPolicy; if (raiseEvents) { var expiringEventArgs = new ExpiringEventArgs <TKey, TValue>(key, item.Value, expirationPolicy); Expiring.SafeInvoke(this, expiringEventArgs); cancel = expiringEventArgs.Cancel; expirationPolicy = expiringEventArgs.ExpirationPolicy; } if (cancel) { if (expirationPolicy == null && _defaultExpirationPolicyInitCode != null) { expirationPolicy = _defaultExpirationPolicyInitCode.Invoke(); } _dictionary[key] = new CacheStorageValueInfo <TValue>(item.Value, expirationPolicy); return(false); } _dictionary.Remove(key); bool dispose = _disposeValuesOnRemoval; if (raiseEvents) { var expiredEventArgs = new ExpiredEventArgs <TKey, TValue>(key, item.Value, dispose); Expired.SafeInvoke(this, expiredEventArgs); dispose = expiredEventArgs.Dispose; } if (dispose) { item.DisposeValue(); } return(true); }
public TValue GetFromCacheOrFetch(TKey key, Func <TValue> code, ExpirationPolicy expirationPolicy, bool @override = false) { Argument.IsNotNull("key", key); Argument.IsNotNull("code", code); return(ExecuteInLock(key, () => { TValue value; var containsKey = _dictionary.ContainsKey(key); if (!containsKey || @override) { value = code.Invoke(); if (!ReferenceEquals(value, null) || _storeNullValues) { if (expirationPolicy == null && _defaultExpirationPolicyInitCode != null) { expirationPolicy = _defaultExpirationPolicyInitCode.Invoke(); } var valueInfo = new CacheStorageValueInfo <TValue>(value, expirationPolicy); lock (_syncObj) { _dictionary[key] = valueInfo; } if (valueInfo.CanExpire) { _checkForExpiredItems = true; } if (expirationPolicy != null) { if (_expirationTimer == null) { UpdateTimer(); } } } } else { value = _dictionary[key].Value; } return value; })); }
/// <summary> /// Adds a value to the cache associated with to a key asynchronously. /// <para /> /// Note that this is a wrapper around <see cref="GetFromCacheOrFetch(TKey,System.Func{TValue},ExpirationPolicy,bool)"/>. /// </summary> /// <param name="key">The key.</param> /// <param name="code">The deferred initialization code of the value.</param> /// <param name="expirationPolicy">The expiration policy.</param> /// <param name="override">Indicates if the key exists the value will be overridden.</param> /// <returns>The instance initialized by the <paramref name="code" />.</returns> /// <exception cref="ArgumentNullException">If <paramref name="key" /> is <c>null</c>.</exception> /// <exception cref="ArgumentNullException">If <paramref name="code" /> is <c>null</c>.</exception> public async Task <TValue> GetFromCacheOrFetchAsync(TKey key, Func <Task <TValue> > code, ExpirationPolicy expirationPolicy, bool @override = false) { Argument.IsNotNull("key", key); Argument.IsNotNull("code", code); lock (GetLockByKey(key)) { var containsKey = _dictionary.ContainsKey(key); if (containsKey && !@override) { return(_dictionary[key].Value); } } var value = await code.Invoke(); lock (GetLockByKey(key)) { if (!ReferenceEquals(value, null) || _storeNullValues) { if (expirationPolicy == null && _defaultExpirationPolicyInitCode != null) { expirationPolicy = _defaultExpirationPolicyInitCode.Invoke(); } var valueInfo = new CacheStorageValueInfo <TValue>(value, expirationPolicy); lock (_syncObj) { _dictionary[key] = valueInfo; } if (valueInfo.CanExpire) { _checkForExpiredItems = true; } if (expirationPolicy != null) { if (_expirationTimer == null) { UpdateTimer(); } } } } return(value); }
/// <summary> /// Adds a value to the cache associated with to a key asynchronously. /// <para /> /// Note that this is a wrapper around <see cref="GetFromCacheOrFetch(TKey,System.Func{TValue},ExpirationPolicy,bool)"/>. /// </summary> /// <param name="key">The key.</param> /// <param name="code">The deferred initialization code of the value.</param> /// <param name="expirationPolicy">The expiration policy.</param> /// <param name="override">Indicates if the key exists the value will be overridden.</param> /// <returns>The instance initialized by the <paramref name="code" />.</returns> /// <exception cref="ArgumentNullException">If <paramref name="key" /> is <c>null</c>.</exception> /// <exception cref="ArgumentNullException">If <paramref name="code" /> is <c>null</c>.</exception> public Task <TValue> GetFromCacheOrFetchAsync(TKey key, Func <Task <TValue> > code, ExpirationPolicy expirationPolicy, bool @override = false) { Argument.IsNotNull("key", key); Argument.IsNotNull("code", code); return(ExecuteInLockAsync(key, async() => { CacheStorageValueInfo <TValue> cacheStorageValueInfo; if (!@override && _dictionary.TryGetValue(key, out cacheStorageValueInfo)) { return cacheStorageValueInfo.Value; } var value = await code(); if (!ReferenceEquals(value, null) || _storeNullValues) { if (expirationPolicy == null && _defaultExpirationPolicyInitCode != null) { expirationPolicy = _defaultExpirationPolicyInitCode(); } var valueInfo = new CacheStorageValueInfo <TValue>(value, expirationPolicy); lock (_syncObj) { _dictionary[key] = valueInfo; } if (valueInfo.CanExpire) { _checkForExpiredItems = true; } if (expirationPolicy != null) { if (_expirationTimer == null) { UpdateTimer(); } } } return value; })); }