예제 #1
0
        /// <summary>
        /// Gets the cache region for the specified invocation.
        /// </summary>
        /// <param name="invocation"></param>
        /// <returns></returns>
        private static string GetCacheRegion(IInvocation invocation)
        {
            string region;
            var    strategy = ResponseDataCachingStrategy.Get(invocation.Method);

            if (strategy != null)
            {
                region = strategy.GetCacheRegion();
                if (!String.IsNullOrEmpty(region))
                {
                    return(region);
                }
            }

            region = string.Format("{0}.{1}", invocation.InvocationTarget.GetType().FullName, invocation.Method.Name);
            return(region);
        }
예제 #2
0
        /// <summary>
        /// Called from subclasses within the intercept method to process the invocation, adding caching as appropriate.
        /// </summary>
        /// <param name="invocation"></param>
        /// <param name="cacheId"></param>
        protected void ProcessInvocation(IInvocation invocation, string cacheId)
        {
            using (var cacheClient = Cache.CreateClient(cacheId))
            {
                var region  = GetCacheRegion(invocation);
                var request = invocation.Arguments[0];

                // check for a cached response, unless it is being explicity bypassed
                // must do this even if this operation does not support caching, because have no way of knowing
                // whether it does or does not support caching
                if (ResponseCacheBypassScope.BypassCount == 0 && GetCachedResponse(invocation, request, cacheClient, region))
                {
                    return;
                }

                // invoke the operation
                invocation.Proceed();

                // Regardless of caching directives, just remove anything the strategy says to when we actually call the method.
                var strategy          = ResponseDataCachingStrategy.Get(invocation.Method);
                var cacheKeysToRemove = strategy.GetCacheKeysToRemove(request, invocation.ReturnValue);
                if (cacheKeysToRemove != null && cacheKeysToRemove.Length > 0)
                {
                    foreach (var cacheKey in cacheKeysToRemove)
                    {
                        cacheClient.Remove(cacheKey, new CacheRemoveOptions(region));
                    }
                }

                // get cache directive
                var directive = GetCachingDirective(invocation);

                // cache the response if directed
                if (directive != null && directive.EnableCaching && directive.TimeToLive > TimeSpan.Zero)
                {
                    CacheResponse(invocation, request, cacheClient, region, directive);
                }
            }
        }
예제 #3
0
        /// <summary>
        /// Puts the invocation response in the specified cache.
        /// </summary>
        /// <param name="invocation"></param>
        /// <param name="cacheClient"></param>
        /// <param name="request"> </param>
        /// <param name="region"></param>
        /// <param name="directive"></param>
        protected static void PutResponseInCache(IInvocation invocation, object request, ICacheClient cacheClient, string region, ResponseCachingDirective directive)
        {
            // bail if the directive does not tell us to cache anything
            if (directive == null || !directive.EnableCaching || directive.TimeToLive == TimeSpan.Zero)
            {
                return;
            }

            var strategy = ResponseDataCachingStrategy.Get(invocation.Method);
            var data     = strategy.GetCacheDataToPut(request, invocation.ReturnValue);

            if (data == null || data.Length == 0)
            {
                throw new InvalidOperationException(
                          string.Format("{0} is cacheable but the caching strategy didn't return any data to put in the cache.", invocation.GetType().FullName));
            }

            foreach (var item in data)
            {
                cacheClient.Put(item.CacheKey, item.Data, new CachePutOptions(region, directive.TimeToLive, false));
            }
        }
예제 #4
0
        /// <summary>
        /// Tries to get a previously cached response for the specified invocation, returning false if not found.
        /// </summary>
        /// <param name="invocation"></param>
        /// <param name="request"> </param>
        /// <param name="cacheClient"></param>
        /// <param name="region"></param>
        /// <returns></returns>
        private static bool GetCachedResponse(IInvocation invocation, object request, ICacheClient cacheClient, string region)
        {
            if (!cacheClient.RegionExists(region))
            {
                return(false);
            }

            var strategy  = ResponseDataCachingStrategy.Get(invocation.Method);
            var cacheKeys = strategy.GetCacheKeys(request);

            if (cacheKeys == null || cacheKeys.Length == 0)
            {
                return(false);
            }

            var cacheData = new Dictionary <string, object>();

            foreach (var cacheKey in cacheKeys)
            {
                var data = cacheClient.Get(cacheKey, new CacheGetOptions(region));
                if (data != null)                 //Assume null is not a relevant cache entry.
                {
                    cacheData[cacheKey] = data;
                }
            }

            if (cacheData.Count > 0)
            {
                var response = strategy.ConstructResponse(request, cacheData);
                if (response != null)
                {
                    invocation.ReturnValue = response;
                    return(true);
                }
            }

            return(false);
        }