3
\$\begingroup\$

I want to realize caching in WCF web service. I'm using the following code:

public interface ICache<T> : IDisposable where T : class
    {
        string Name { get; }
        CacheItemPolicy CacheItemPolicy { get; set; }
        long Count { get; }
        bool IsDisposed { get; }
        void AddOrUpdate(string key, T value);
        bool TryGetValue(string key, out T value);
        T GetValue(string key);
        bool TryRemove(string key, out T value);
        void Remove(string key);
        bool ContainsKey(string key);
    }

public class MemoryCacheWrapper<T> : ICache<T> where T : class
    {
        private readonly MemoryCache _memoryCache;
        private CacheItemPolicy _cacheItemPolicy;
        private bool _isDisposed;

        public MemoryCacheWrapper(string name, NameValueCollection config = null)
        {
            _memoryCache = config != null ? new MemoryCache(name, config) : new MemoryCache(name);
            _isDisposed = false;                
        }

        public string Name
        {
            get { return _memoryCache.Name; }
        }

        public long CacheMemoryLimitInBytes
        {
            get { return _memoryCache.CacheMemoryLimit; }
        }

        public long PhysicalMemoryLimit
        {
            get { return _memoryCache.PhysicalMemoryLimit; }
        }

        public TimeSpan PollingInterval
        {
            get { return _memoryCache.PollingInterval; }
        }

        public CacheItemPolicy CacheItemPolicy
        {
            get
            {
                return _cacheItemPolicy;
            }
            set
            {
                if (value != null)
                {
                    _cacheItemPolicy = value;
                }
            }
        }

        public void AddOrUpdate(string key, T value)
        {
            _memoryCache.Set(key, value, CacheItemPolicy);
        }

        public bool TryGetValue(string key, out T value)
        {
            bool result = false;
            value = default(T);

            object item = _memoryCache.Get(key);
            if (item != null)
            {
                value = (T)item;
                result = true;
            }

            return result;
        }

        public T GetValue(string key)
        {
            return (T)_memoryCache.Get(key);
        }

        public bool TryRemove(string key, out T value)
        {
            bool result = false;
            value = default(T);

            object item = _memoryCache.Remove(key);
            if (item != null)
            {
                result = true;
                value = (T)item;
            }

            return result;
        }

        public void Remove(string key)
        {
            _memoryCache.Remove(key);
        }

        public bool ContainsKey(string key)
        {
            return _memoryCache.Contains(key);
        }

        public long Count
        {
            get { return _memoryCache.GetCount(); }
        }

        ~MemoryCacheWrapper()
        {
            Dispose(false);
        }

        public void Dispose()
        {
            Dispose(true);
            GC.SuppressFinalize(this);
        }

        private void Dispose(bool disposing)
        {
            if (!this._isDisposed)
            {
                if (disposing)
                {
                    _memoryCache.Dispose();
                }
            }
            _isDisposed = true;
        }

        public bool IsDisposed
        {
            get { return _isDisposed; }
        }
    }

This is my service:

[ServiceBehavior(InstanceContextMode = InstanceContextMode.Single)]
    public class PremieraInteraction : IPremieraInteraction
    {
        private ICache<InfoLevel> _cacheInfoLevel = new MemoryCacheWrapper<InfoLevel>("MyCache");

        public string GetPlacesInfoForSession(int levelId, int clientId, int sessionId)
        {
            var key = CacheUtils.GenerateKeyForCache(JobName.PlacesInfoForSession.ToString(),clientId, sessionId, levelId);
            JavaScriptSerializer serializer = new JavaScriptSerializer();

            InfoLevel cachedInfoLevel;
            if (_cacheInfoLevel.TryGetValue(key, out cachedInfoLevel))
                return serializer.Serialize(new { Success = true, Count = cachedInfoLevel.AllPlacesCount, Free = cachedInfoLevel.FreePlaces });

            return serializer.Serialize(new { Success = false, Message = "Some error" });
        }
    }

What you think about this code?
This is not bad that I create MemoryCacheWrapper inside service and not static?
Also, MemoryCacheWrapper are generic. In the future, I need to create several MemoryCacheWrapper instances:

    private ICache<InfoLevel> _cacheInfoLevel = new MemoryCacheWrapper<InfoLevel>("MyCache");
    private ICache<OtherObject> _cacheOtherObject= new MemoryCacheWrapper<OtherObject>("MyCache");

Any suggestions are helpful.

\$\endgroup\$
  • \$\begingroup\$ Are you self-hosting the service or are you using IIS to host the service? \$\endgroup\$ – Kane Jun 22 '12 at 1:36
  • \$\begingroup\$ @Kane: I'm using IIS. Sorry fo delay. \$\endgroup\$ – user348173 Jun 26 '12 at 11:51
2
\$\begingroup\$

I think you have created an unuseful abstraction. Mostly your methods only calling the underlaying MemoryCache instance and you have created something weird: IDisposable wrapper over a static instance. Of yourse the MemoryCache can be disposed but not this way. You have a service with InstanceContextMode.Single then you should only call dispose or provide oppurtunity to call the Dispose method when your service stops.

Insted of your wrapper i would create some extension method for the typed get/remove logic wrappings:

public static class MemoryCacheExtensions
{
    public static bool TryGetValue<T>(this MemoryCache _memoryCache, string key, out T value)
    {
        var item = _memoryCache.Get(key);
        if (item != null)
        {
            value = (T)item;
            return true;
        }

        value = default(T);
        return false;
    }

    public static T GetValue<T>(this MemoryCache _memoryCache, string key)
    {
        return (T)_memoryCache.Get(key);
    }

    public static bool TryRemove<T>(this MemoryCache _memoryCache, string key, out T value)
    {
        var item = _memoryCache.Remove(key);
        if (item != null)
        {
            value = (T)item;
            return true;
        }
        value = default(T);
        return result;
    }
}
| improve this answer | |
\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.