256 lines
9.3 KiB
C#
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();
|
|
}
|
|
}
|
|
} |