VEU.WathBody/3-app/1-lib/Kit.Helpers/Cache/CacheProvider.cs

256 lines
9.3 KiB
C#

namespace Kit.Helpers.Cache
{
using Microsoft.Extensions.Caching.Memory;
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
public enum CacheLevels { None = 100, Database = 1, ClientFilter=3, Convert=5, ConvertFilter=7, Sorting=9, Paging=11 }
public interface ICacheParameter
{
CacheLevels CachingLevel { get; }
string GetCacheKey(CacheLevels cachingMode);
bool IsCache(CacheLevels cachingMode);
}
public class CacheSetProperties
{
public bool EnableCaching { get; set; }
public Int32 DurationSeconds { get; set; }
public Int32 SlidingSeconds { get; set; }
}
public class CacheProvider : ICacheProvider
{
public Dictionary<string, object> CacheCollection = new Dictionary<string,object>();
private Dictionary<string, object> LockObjects = new Dictionary<string, object>(1000);
private object m_keysLock = new object();
private IMemoryCache Cache;
private object m_lock = new object();
public CacheProvider(IMemoryCache memoryCache)
{
Cache = memoryCache;
}
private IList<string> GetCacheKeys()
{
var field = typeof(MemoryCache).GetProperty("EntriesCollection", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance);
var collection = field.GetValue(Cache) as ICollection;
var items = new List<string>();
if (collection != null)
foreach (var item in collection)
{
var methodInfo = item.GetType().GetProperty("Key");
var val = methodInfo.GetValue(item);
items.Add(val.ToString());
}
return items;
}
public void PurgeCacheItem(string prefix, ICacheParameter parameters, CacheLevels cachingMode)
{
string cacheName = GetCacheKey(prefix, parameters, cachingMode);
if (this.Cache != null)
{
//формируем список ключей для удаления из кэша
List<string> itemsToRemove = new List<string>();
IList<string> cacheKeys = this.GetCacheKeys();
foreach (string key in cacheKeys)
{
if (key.ToLowerEquals(cacheName))
{
itemsToRemove.Add(key);
}
}
//удаляем элементы кэша
foreach (string key in itemsToRemove)
{
this.Cache.Remove(key);
}
}
else
{
var itemToRemoveKeys = CacheCollection.Where(x => x.Key.ToLowerEquals(cacheName)).Select(x => x.Key);
foreach (var key in itemToRemoveKeys)
{
lock (GetLockObject(key)) { CacheCollection.Remove(key); }
lock (LockObjects) { LockObjects.Remove(key); }
}
}
}
public void PurgeCacheItems(string prefix)
{
prefix = prefix.ToLower();
if (this.Cache != null)
{
//формируем список ключей для удаления из кэша
List<string> itemsToRemove = new List<string>();
IList<string> cacheKeys = this.GetCacheKeys();
foreach (string key in cacheKeys)
{
if (key.ToLower().StartsWith(prefix))
{
itemsToRemove.Add(key);
}
}
//удаляем элементы кэша
foreach (string key in itemsToRemove)
{
this.Cache.Remove(key);
}
}
else
{
var itemToRemoveKeys = from di in CacheCollection
where di.Key.ToLower().StartsWith(prefix)
select di.Key;
foreach (var key in itemToRemoveKeys)
{
lock (GetLockObject(key)) { CacheCollection.Remove(key); }
lock (LockObjects) { LockObjects.Remove(key); }
}
}
}
public bool Contains(string cacheName)
{
if (this.Cache == null) return CacheCollection.ContainsKey(cacheName);
return this.Cache.TryGetValue(cacheName, out object obj);
}
public void SetCacheData(string key, object data, CacheSetProperties setProperties)
{
if (setProperties.EnableCaching && data != null)
{
if (this.Cache == null)
{
if (CacheCollection.ContainsKey(key))
CacheCollection[key] = data;
else
CacheCollection.Add(key, data);
}
else
{
var cacheEntryOptions = new MemoryCacheEntryOptions()
.SetSlidingExpiration(TimeSpan.FromSeconds(setProperties.SlidingSeconds))
.SetAbsoluteExpiration(TimeSpan.FromSeconds(setProperties.DurationSeconds))
.SetPriority(CacheItemPriority.Normal)
//.SetSize(1024)
;
this.Cache.Set(key, data, cacheEntryOptions);
}
}
}
public object GetCacheData(string cacheName)
{
if (Cache == null)
{
if (CacheCollection.ContainsKey(cacheName)) return CacheCollection[cacheName];
return null;
}
if (!this.Contains(cacheName))
{
return null;
}
if (this.Cache.TryGetValue(cacheName, out object obj))
{
return obj;
}
return null;
}
public object GetLockObject(string cacheName)
{
lock (m_keysLock)
{
if (!this.LockObjects.ContainsKey(cacheName)) this.LockObjects.Add(cacheName, new object());
return this.LockObjects[cacheName];
}
}
public delegate TResult GetData<TResult>();
public TResult GetCacheData<TResult>(string prefix, ICacheParameter parameters, CacheLevels cachingMode, Func<TResult> getMethod)
{
CacheSetProperties setProperties = new CacheSetProperties{
EnableCaching = true,
DurationSeconds = 6000,
SlidingSeconds = 60
};
return GetCacheData<TResult>(prefix, parameters, cachingMode, getMethod, setProperties);
}
public TResult GetCacheData<TResult>(string prefix, ICacheParameter parameters, CacheLevels cachingMode, Func<TResult> getMethod, CacheSetProperties setProperties)
{
object data = null;
string cacheName = GetCacheKey(prefix, parameters, cachingMode);
if (!cacheName.IsNullOrEmpty())
{
data = GetCacheData(cacheName);
if (data != null && data is TResult) return (TResult)data;
lock (this.GetLockObject(cacheName))
{
data = this.GetCacheData(cacheName);
if (data == null) data = getMethod();
this.SetCacheData(cacheName, data, setProperties);
}
}
else
{
data = getMethod();
}
return (TResult)data;
}
public string GetCacheKey(string prefix, ICacheParameter parameters, CacheLevels cachingMode)
{
bool isCache = parameters != null && parameters.IsCache(cachingMode);
return (isCache ? String.Format("{0}_{1}", prefix, parameters.GetCacheKey(cachingMode)) : String.Empty);
}
public void ClearCacheData(string key)
{
throw new NotImplementedException();
}
public string CreateCacheName(object prefix, params object[] args)
{
throw new NotImplementedException();
}
public void PurgeCacheItems(string cacheName, bool isPrefix = false)
{
throw new NotImplementedException();
}
public void SetCacheData<TObject>(string cacheName, TObject data, MemoryCacheEntryOptions setProperties = null)
{
throw new NotImplementedException();
}
public TResult GetCacheData<TResult>(string cacheName)
{
throw new NotImplementedException();
}
public TResult GetCacheData<TResult>(string cacheName, Func<TResult> getMethod, MemoryCacheEntryOptions setProperties = null)
{
throw new NotImplementedException();
}
public TResult GetCacheData<TResult>(string cacheName, Func<TResult> getMethod, MemoryCacheEntryOptions setProperties = null, PostEvictionDelegate callback = null)
{
throw new NotImplementedException();
}
}
}