97 lines
3.7 KiB
C#
97 lines
3.7 KiB
C#
using Microsoft.Extensions.Caching.Memory;
|
|
using Kit.Helpers;
|
|
|
|
namespace Kit.Helpers.Cache
|
|
{
|
|
public abstract class BaseCacheProvider : ICacheProvider
|
|
{
|
|
|
|
private readonly Dictionary<string, object> _lockObjects = new Dictionary<string, object>(1000);
|
|
|
|
private readonly object _keysLock = new object();
|
|
|
|
public abstract bool Contains(string cacheName);
|
|
public abstract void PurgeCacheItems(string cacheName, bool isPrefix = false);
|
|
public abstract void SetCacheData<TObject>(string cacheName, TObject data, MemoryCacheEntryOptions? setProperties = null, PostEvictionDelegate? callback = null);
|
|
public abstract TResult GetCacheData<TResult>(string cacheName);
|
|
|
|
protected string CacheNameNormalize(string casheName)
|
|
{
|
|
if (casheName == null) return string.Empty;
|
|
|
|
return casheName.ToLower();
|
|
}
|
|
protected object GetLockObject(string cacheName)
|
|
{
|
|
lock (_keysLock)
|
|
{
|
|
if (!this._lockObjects.ContainsKey(cacheName)) this._lockObjects.Add(cacheName, new object());
|
|
return this._lockObjects[cacheName];
|
|
}
|
|
}
|
|
|
|
public virtual string CreateCacheName(object prefix, params object[] args)
|
|
{
|
|
prefix = prefix != null ? prefix.ToString()!.AddSufixIsNotEmpty("_") : string.Empty;
|
|
|
|
string end = string.Empty;
|
|
if (!args.IsNullOrEmpty())
|
|
{
|
|
end = args.Where(x => x != null).Select(x => x.ToString()).Join("_");
|
|
}
|
|
|
|
return $"{prefix}{end}";
|
|
}
|
|
|
|
public virtual TResult GetCacheData<TResult>(string cacheName, Func<TResult> getMethod, MemoryCacheEntryOptions setProperties = null)
|
|
{
|
|
cacheName = CacheNameNormalize(cacheName);
|
|
|
|
Check.ArgumentIsNotNull(getMethod, "getMethod");
|
|
if (cacheName.IsNullOrEmpty()) return (TResult)getMethod();
|
|
|
|
// если есть данные в кеше но возвращаем
|
|
TResult data = GetCacheData<TResult>(cacheName);
|
|
if (data != null) return data;
|
|
|
|
lock (this.GetLockObject(cacheName))
|
|
{
|
|
// повторная проверка после блокировки
|
|
data = this.GetCacheData<TResult>(cacheName);
|
|
if (data != null) return data;
|
|
|
|
// если в кеше данных нет то выполняем метод
|
|
data = getMethod();
|
|
this.SetCacheData(cacheName, data, setProperties);
|
|
}
|
|
|
|
return data;
|
|
}
|
|
|
|
public TResult GetCacheData<TResult>(string cacheName, Func<TResult> getMethod, MemoryCacheEntryOptions? setProperties = null, PostEvictionDelegate? callback = null)
|
|
{
|
|
cacheName = CacheNameNormalize(cacheName);
|
|
|
|
Check.ArgumentIsNotNull(getMethod, "getMethod");
|
|
if (cacheName.IsNullOrEmpty()) return (TResult)getMethod();
|
|
|
|
// если есть данные в кеше но возвращаем
|
|
TResult data = GetCacheData<TResult>(cacheName);
|
|
if (data != null) return data;
|
|
|
|
lock (this.GetLockObject(cacheName))
|
|
{
|
|
// повторная проверка после блокировки
|
|
data = this.GetCacheData<TResult>(cacheName);
|
|
if (data != null) return data;
|
|
|
|
// если в кеше данных нет то выполняем метод
|
|
data = getMethod();
|
|
this.SetCacheData(cacheName, data, setProperties, callback);
|
|
}
|
|
|
|
return data;
|
|
}
|
|
}
|
|
}
|