示例#1
0
        /// <inheritdoc />
        public object Get(string key, Func <object> factory, TimeSpan?timeout, bool isSliding = false, string[] dependentFiles = null)
        {
            // see notes in HttpRuntimeAppCache

            Lazy <object> result;

            using (var lck = new UpgradeableReadLock(_locker))
            {
                result = MemoryCache.Get(key) as Lazy <object>;
                if (result == null || SafeLazy.GetSafeLazyValue(result, true) == null) // get non-created as NonCreatedValue & exceptions as null
                {
                    result = SafeLazy.GetSafeLazy(factory);
                    var policy = GetPolicy(timeout, isSliding, dependentFiles);

                    lck.UpgradeToWriteLock();
                    //NOTE: This does an add or update
                    MemoryCache.Set(key, result, policy);
                }
            }

            //return result.Value;

            var value = result.Value; // will not throw (safe lazy)

            if (value is SafeLazy.ExceptionHolder eh)
            {
                eh.Exception.Throw();                                       // throw once!
            }
            return(value);
        }
示例#2
0
 /// <inheritdoc />
 public void Insert(string key, Func <object> factory, TimeSpan?timeout = null, bool isSliding = false, string[] dependentFiles = null)
 {
     InnerCache.Insert(key, () =>
     {
         var result = SafeLazy.GetSafeLazy(factory);
         var value  = result.Value; // force evaluation now - this may throw if cacheItem throws, and then nothing goes into cache
         // do not store null values (backward compat), clone / reset to go into the cache
         return(value == null ? null : CheckCloneableAndTracksChanges(value));
     }, timeout, isSliding, dependentFiles);
 }
示例#3
0
        /// <inheritdoc />
        public object Get(string key, Func <object> factory)
        {
            var cached = InnerCache.Get(key, () =>
            {
                var result = SafeLazy.GetSafeLazy(factory);
                var value  = result.Value; // force evaluation now - this may throw if cacheItem throws, and then nothing goes into cache
                // do not store null values (backward compat), clone / reset to go into the cache
                return(value == null ? null : CheckCloneableAndTracksChanges(value));
            });

            return(CheckCloneableAndTracksChanges(cached));
        }
示例#4
0
        /// <inheritdoc />
        public override object Get(string key, Func <object> factory)
        {
            //no place to cache so just return the callback result
            if (!TryGetContextItems(out var items))
            {
                return(factory());
            }

            key = GetCacheKey(key);

            Lazy <object> result;

            try
            {
                EnterWriteLock();
                result = items[key] as Lazy <object>; // null if key not found

                // cannot create value within the lock, so if result.IsValueCreated is false, just
                // do nothing here - means that if creation throws, a race condition could cause
                // more than one thread to reach the return statement below and throw - accepted.

                if (result == null || SafeLazy.GetSafeLazyValue(result, true) == null) // get non-created as NonCreatedValue & exceptions as null
                {
                    result     = SafeLazy.GetSafeLazy(factory);
                    items[key] = result;
                }
            }
            finally
            {
                ExitWriteLock();
            }

            // using GetSafeLazy and GetSafeLazyValue ensures that we don't cache
            // exceptions (but try again and again) and silently eat them - however at
            // some point we have to report them - so need to re-throw here

            // this does not throw anymore
            //return result.Value;

            var value = result.Value; // will not throw (safe lazy)

            if (value is SafeLazy.ExceptionHolder eh)
            {
                eh.Exception.Throw();                                       // throw once!
            }
            return(value);
        }
示例#5
0
        /// <inheritdoc />
        public void Insert(string key, Func <object> factory, TimeSpan?timeout = null, bool isSliding = false, string[] dependentFiles = null)
        {
            // NOTE - here also we must insert a Lazy<object> but we can evaluate it right now
            // and make sure we don't store a null value.

            var result = SafeLazy.GetSafeLazy(factory);
            var value  = result.Value; // force evaluation now

            if (value == null)
            {
                return;                // do not store null values (backward compat)
            }
            var policy = GetPolicy(timeout, isSliding, dependentFiles);

            //NOTE: This does an add or update
            MemoryCache.Set(key, result, policy);
        }
示例#6
0
        /// <inheritdoc />
        public object Get(string cacheKey, Func <object> getCacheItem)
        {
            var result = _items.GetOrAdd(cacheKey, k => SafeLazy.GetSafeLazy(getCacheItem));

            var value = result.Value; // will not throw (safe lazy)

            if (!(value is SafeLazy.ExceptionHolder eh))
            {
                return(value);
            }

            // and... it's in the cache anyway - so contrary to other cache providers,
            // which would trick with GetSafeLazyValue, we need to remove by ourselves,
            // in order NOT to cache exceptions

            _items.TryRemove(cacheKey, out result);
            eh.Exception.Throw(); // throw once!
            return(null);         // never reached
        }