{"id":894,"date":"2018-03-19T17:59:10","date_gmt":"2018-03-19T16:59:10","guid":{"rendered":"https:\/\/solidt.eu\/site\/?p=894"},"modified":"2019-12-02T17:20:32","modified_gmt":"2019-12-02T16:20:32","slug":"c-in-memory-cache","status":"publish","type":"post","link":"https:\/\/solidt.eu\/site\/c-in-memory-cache\/","title":{"rendered":"C# In-Memory Cache"},"content":{"rendered":"\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"csharp\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">using System;\nusing System.Runtime.Caching;\n\nnamespace Default\n{\n    public class CacheHelper\n    {\n        private static readonly ObjectCache Cache = MemoryCache.Default;\n\/\/        private static readonly ObjectCache ObjectCache = new MemoryCache(\"WebApiCache\");\n        private static ConcurrentDictionary&lt;string, object> keyLocks = new ConcurrentDictionary&lt;string, object>();\n        public static T Get&lt;T>(string key)\n        {\n            return (T)Cache.Get(key);\n        }\n\n        public static void Add(string key, object value, int minutes)\n        {\n            var item = new CacheItem(key) {Value = value};\n            var policy = new CacheItemPolicy {AbsoluteExpiration = DateTime.UtcNow.AddMinutes(minutes)};\n            Cache.Add(item, policy);\n        }\n        public static T GetFromCache&lt;T>(string key)\n        {\n            return (T)(ObjectCache.GetCacheItem(key)?.Value);\n        }\n\n        public static void AddToCacheNonExpiring(string key, object value)\n        {\n            var policy = new CacheItemPolicy { AbsoluteExpiration = DateTimeOffset.MaxValue };\n\n            var cacheItem = new CacheItem(key, value);\n            ObjectCache.Add(cacheItem, policy);\n        }\n\n        public static void AddToCacheAbsolute(string key, object value, DateTimeOffset expiresAt)\n        {\n            var policy = new CacheItemPolicy { AbsoluteExpiration = expiresAt };\n\n            var cacheItem = new CacheItem(key, value);\n            ObjectCache.Add(cacheItem, policy);\n        }\n\n        public static async Task&lt;T> CachedItem&lt;T>(string key, Func&lt;Task&lt;T>> generator, TimeSpan validTime)\n        {\n            using (new Locker(key))\n            {\n                var cacheValue = ObjectCache.GetCacheItem(key)?.Value;\n                if (cacheValue != null)\n                    return (T)cacheValue;\n                T result = await generator().ConfigureAwait(false); \/\/ Configure await false ensures the function throws errors\n                var cacheItem = new CacheItem(key, result);\n                var policy = new CacheItemPolicy { AbsoluteExpiration = DateTimeOffset.Now.Add(validTime) };\n                ObjectCache.Add(cacheItem, policy);\n                return result;\n            }\n        }\n\n        public static T CachedItem2&lt;T>(string key, Func&lt;T> generator, TimeSpan validTime)\n        {\n            try\n            {\n                lock (keyLocks.GetOrAdd(key, new object()))\n                {\n                    var policy = new CacheItemPolicy { AbsoluteExpiration = DateTimeOffset.Now.Add(validTime) };\n\n                    var cacheValue = ObjectCache.GetCacheItem(key)?.Value;\n                    if (cacheValue != null)\n                        return (T)cacheValue;\n                    \/\/ Configure await false ensures the function throws errors;\n                    T result = generator();\n                    if (result == null)\n                        return default(T); \/\/ null can not be cached\n                    var cacheItem = new CacheItem(key, result);\n                    ObjectCache.Add(cacheItem, policy);\n                    return result;\n                }\n            }\n            finally\n            {\n                keyLocks.TryRemove(key, out object _);\n            }\n        }\n\n        private class CachedData&lt;T> : ICachedItem&lt;T>\n        {\n            public DateTime GeneratedAt { get; set; }\n            public T Result { get; set; }\n        }\n\n\n        public ICachedItem&lt;T> CachedItem&lt;T>(string key, Func&lt;T> generator, TimeSpan validTime, TimeSpan regenerateAfter)\n        {\n            var cachedData = (CachedData&lt;T>)ObjectCache.GetCacheItem(key)?.Value;           \n            if (cachedData != null) {\n                if (cachedData.GeneratedAt &lt; DateTime.Now.Subtract(regenerateAfter)) { \n                    Task.Run(() => { \n                        return GenerateNew(key, generator, validTime);    \n                    });\n                }\n                return cachedData;\n            }\n            return GenerateNew(key, generator, validTime);    \n        }\n\n        public ICachedItem&lt;T> GenerateNew&lt;T>(string key, Func&lt;T> generator, TimeSpan validTime) { \n            var result = generator();\n            if (result == null)\n                return default; \/\/ null can not be cached\n\n            var data = new CachedData&lt;T> { \n                GeneratedAt = DateTime.Now,\n                Result = result\n            };\n            var cacheItem = new CacheItem(key, data);\n            var policy = new CacheItemPolicy { AbsoluteExpiration = DateTimeOffset.Now.Add(validTime)};\n            ObjectCache.Set(cacheItem, policy);\n            return data;\n        }\n    }\n}\n<\/pre>\n\n\n\n<p><\/p>\n","protected":false},"excerpt":{"rendered":"","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"inline_featured_image":false,"footnotes":""},"categories":[6],"tags":[],"class_list":["post-894","post","type-post","status-publish","format-standard","hentry","category-dotnet"],"_links":{"self":[{"href":"https:\/\/solidt.eu\/site\/wp-json\/wp\/v2\/posts\/894","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/solidt.eu\/site\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/solidt.eu\/site\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/solidt.eu\/site\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/solidt.eu\/site\/wp-json\/wp\/v2\/comments?post=894"}],"version-history":[{"count":15,"href":"https:\/\/solidt.eu\/site\/wp-json\/wp\/v2\/posts\/894\/revisions"}],"predecessor-version":[{"id":2981,"href":"https:\/\/solidt.eu\/site\/wp-json\/wp\/v2\/posts\/894\/revisions\/2981"}],"wp:attachment":[{"href":"https:\/\/solidt.eu\/site\/wp-json\/wp\/v2\/media?parent=894"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/solidt.eu\/site\/wp-json\/wp\/v2\/categories?post=894"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/solidt.eu\/site\/wp-json\/wp\/v2\/tags?post=894"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}