Tuesday 9 July 2013

Generic Cache Manager


To improve the performance of an application many a times we need to cache frequently used data. This generic cache manager will help to maintain cache using concurrent dictionary (Key, Value Pair). Concurrent Dictionary represents a thread-safe collection of key/value pairs that can be accessed by multiple threads concurrently.

Generic cache manager allows you to add, delete and retrieve data from the concurrent dictionary.

If you are using dependency injection or container like Unity, Windsor-Castle etc. in your application then you have to register cache manager as a Singleton. Otherwise you can achieve a singleton pattern by making CacheManager class and its method as a static. Following is the generic Cache Manager code.

    using System;

    public interface ICacheManager
    {
        /// <summary>
        /// Add a new object into the cache
        /// </summary>
        /// <param name="key">The key of the object to add</param>
        /// <param name="value">The value of the object to add</param>
        void Add(string key, object value);

        /// <summary>
        /// Check whether the key is contained by the cache
        /// </summary>
        /// <param name="key">The key to check</param>
        /// <returns>Returns true if the key is contained by the cache</returns>
        bool Contains(string key);

        /// <summary>
        /// Returns the number of items in the cache
        /// </summary>
        /// <returns></returns>
        int Count();

        /// <summary>
        /// Get the object that its key is given
        /// </summary>
        /// <typeparam name="T">The object</typeparam>
        /// <param name="key">The given key to check</param>
        /// <returns>returns the object or null if it doesn't exists</returns>
        T Get<T>(string key);

        /// <summary>
        /// Get the object that its key is given
        /// </summary>
        /// <typeparam name="T">The object</typeparam>
        /// <param name="key">The given key to check</param>
        /// <param name="getData">Function that retrieves the data </param>
        /// <returns>returns the object or null if it doesn't exists</returns>
        T SafeGet<T>(string key, Func<T> getData);

        /// <summary>
        /// Removes the object that is referenced by the given key
        /// </summary>
        /// <param name="key">The given key</param>
        bool Remove(string key);
    }




    using System;
    using System.Collections.Concurrent;


    public class CacheManager : ICacheManager
    {
        private readonly ConcurrentDictionary<string, object> cache;

        public CacheManager()
        {
            cache = new ConcurrentDictionary<string, object>();
        }

        public void Add(string key, object value)
        {
            cache.AddOrUpdate(key, value, (newKey, newValue) => value);
        }

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

        public int Count()
        {
            return cache.Count;
        }

        public T Get<T>(string key)
        {
            return cache.ContainsKey(key) ? (T) cache[key] : default(T);
        }

        public T SafeGet<T>(string key, Func<T> getData)
        {
            return (T) cache.GetOrAdd(key, x => getData());
        }

        public bool Remove(string key)
        {
            object output;
            return cache.TryRemove(key, out output);
        }
    }


Example: 

How to add objects or data into the cache.

cacheManager.Add(<<key>>, <<data>>);

How to get data from the cache.

var cacheData = _cacheManager.Get<T>(<<key>>);

Custome Service Class to connect wcf service

  using  System; using  System.ServiceModel; namespace Custom.Service.Client {      // Borrowed from: http://old.iserviceoriented.com/blog/p...