Kit.Core/LibCommon/Kit.Core.Helpers/Cache/BaseCacheProvider.cs

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;
}
}
}