/// <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); }
/// <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); } } }
/// <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)); } }
/// <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); }