Thursday 12 April 2018

Simple In-memory implementation in C# using MemoryCache Class

In-Memory features, suitable for windows app and services. It also support change monitoring for its dependency. Available from .NET 4.0 +. We can store any type of object in cache.
Support for various callback like: On CacheEntryRemovedCallback, CacheEntryUpdateCallback.

By default available in asp.net. Reference http://www.asptricks.net/2016/12/aspnet-caching-technique-with-example.html

using System;
using System.Runtime.Caching;
using Newtonsoft.Json;
 
namespace MemCached
{
    class CacheItem
    {
        public string Data { getset; }
        public DateTime ModifiedOn { getset; }
        public string Key { getset; }
 
    }
 
    class Program
    {
 
        readonly static ObjectCache memoryCache;
        readonly static CacheItemPolicy policy;
        readonly static int minimumActiveDurationInSecond;
        private static CacheEntryRemovedCallback removeCallback = null;

 
        static Program()
        {
            minimumActiveDurationInSecond = 30;//max idle timeout 
 
            memoryCache = MemoryCache.Default; //Define default Region 
            policy = new CacheItemPolicy();
 
            //SlidingExpiration define max idle time for cache object based on uses.
            //We must set AbsoluteExpiration to DateTimeOffset.MaxValue if we use SlidingExpiration.
            policy.AbsoluteExpiration = DateTimeOffset.MaxValue;
            policy.SlidingExpiration = TimeSpan.FromSeconds(minimumActiveDurationInSecond);



            //RemovedCallback will call once Cached Item will be expired. 
            //We can use either CacheEntryUpdateCallback or CacheEntryRemovedCallback once. Other one should be null.
            removeCallback = new CacheEntryRemovedCallback(OnExpire);
            policy.RemovedCallback = removeCallback;
 
        }
 
 
 
        static void Main(string[] args)
        {
 
            ConsoleKeyInfo cki = new ConsoleKeyInfo();
 
            do
            {
 
                Console.WriteLine("Enter Key");
                var key = Console.ReadLine();
 
                CacheItem data = null;
                if (!memoryCache.Contains(key))
                {
                    Console.WriteLine($"Key [{key}] not found. Set value? Y/N");
                    if (Console.ReadLine().ToLower() == "y")
                    {
                        Console.WriteLine($"Set value for Key [{key}].");
                        data = createCacheData(key, Console.ReadLine());
                    }
                    else
                    {
                        continue;
                    }
 
                }
                else
                {
                    data = getCachedData(key);
                }
 
                if (data != null)
                {
                    Console.WriteLine("Data--------" + JsonConvert.SerializeObject(data));
 
 
                    Console.WriteLine("Do you want to change cached value? Y/N");
                    if (Console.ReadLine().ToLower() == "y")
                    {
                        Console.WriteLine($"Set value for Key [{key}].");
                        data = createCacheData(key, Console.ReadLine());
                    }
                    else
                    {
                        continue;
                    }
                }
 
 
                Console.WriteLine("Press the Escape (Esc) key to quit, Any key to continue.\n");
                cki = Console.ReadKey();
 
            } while (cki.Key != ConsoleKey.Escape);
 
        }
 
 
        /// <summary>
        /// Get Cache Item
        /// </summary>
        /// <param name="key"></param>
        /// <returns></returns>
        public static CacheItem getCachedData(string key)
        {
            CacheItem data = null;
            key = key.ToLower();
            if (memoryCache.Contains(key))
            {
                var cacheItem = (CacheItem)memoryCache[key];
                data = cacheItem;
            }
            return data;
        }
 
        /// <summary>
        /// Make Entry in Cache with customized cache policy.
        /// </summary>
        /// <param name="key"></param>
        /// <param name="value"></param>
        /// <returns></returns>
        public static CacheItem createCacheData(string key, string value)
        {
            var cacheItem = new CacheItem
            {
                Data = value,
                ModifiedOn = DateTime.Now,
                Key = key
            };
 
            if (memoryCache.Contains(key))
            {
                CacheItem source = (CacheItem)memoryCache.Get(key);
                CacheItem updated = cacheItem;
                memoryCache.Remove(key);
                memoryCache.Set(key, cacheItem, policy);
                OnUpdate(source, updated);
 
            }
            else
            {
                memoryCache.Set(key, cacheItem, policy);
            }
            return cacheItem;
        }
 
 
        public static void OnExpire(CacheEntryRemovedArguments cacheEntryRemovedArguments)
        {
            Console.WriteLine($"Key [{cacheEntryRemovedArguments.CacheItem.Key}] Expired. Reason: {cacheEntryRemovedArguments.RemovedReason.ToString()}");
        }
 
 
        public static void OnUpdate(CacheItem source, CacheItem updated)
        {
            Console.WriteLine($"Key [{source.Key}] Updated.");
            Console.WriteLine("Source--------" + JsonConvert.SerializeObject(source));
            Console.WriteLine("Updated--------" + JsonConvert.SerializeObject(updated));
        }
 
    }
}