public class CachingOperationInvoker : Attribute, IOperationBehavior,IOperationInvoker { readonly IOperationInvoker _originalInvoker; readonly double _cacheDuration; public CachingOperationInvoker(IOperationInvoker originalInvoker, double cacheDuration) { _originalInvoker = originalInvoker; _cacheDuration = cacheDuration; } public double SecondsToCache { get; set; } #region Implementation of IOperationInvoker public object Invoke(object instance, object[] inputs, out object[] outputs) { ObjectCache cache = GetCache(); string cacheKey = CreateCacheKey(inputs); CachedResult cacheItem = cache[cacheKey] as CachedResult; if (cacheItem != null) { outputs = cacheItem.Outputs; return cacheItem.ReturnValue; } object result = _originalInvoker.Invoke(instance, inputs, out outputs); cacheItem = new CachedResult { ReturnValue = result, Outputs = outputs }; cache.Add(cacheKey, cacheItem, DateTimeOffset.UtcNow.Add(TimeSpan.FromSeconds(_cacheDuration))); return result; } #endregion #region Implementation of IOperationBehavior public void ApplyDispatchBehavior(OperationDescription operationDescription, DispatchOperation dispatchOperation) { dispatchOperation.Invoker = new CachingOperationInvoker(dispatchOperation.Invoker, SecondsToCache); } #endregionNow you can easily decorate your operation with the attribute
[CachingOperationInvoker(SecondsToCache = 100)] Product GetProduct(int id);
One thing I would like to point out here is that the caching is happening at the server level which will mean that it will go through the wcf pipeline, the saving which we are doing here is the actual operation call. The other approach to consider here would be to come up with caching logic at the client side. Unlike REST services, SOAP services don’t have any standard way of defining caching options for their operations.