#region Copyright (C) 2016 Kevin (OSS开源系列) 公众号:OSSCore
/***************************************************************************
* 文件功能描述:全局插件 - 缓存插件辅助类
*
* 创建人: Kevin
* 创建人Email:1985088337@qq.com
*
*
*****************************************************************************/
#endregion
namespace OSS.Tools.Cache
{
///
/// 缓存的辅助类
///
public static class CacheHelper
{
private static IToolCache DefaultCacheTool { get; set; } = new DefaultToolCache();
///
/// 缓存来源提供者
///
public static Func? CacheToolProvider { get; set; }
///
/// 来源名称格式化
///
public static Func? SourceFormat { get; set; }
///
/// 通过来源名称获取
///
///
///
public static IToolCache GetCache(string sourceName= "")
{
if (SourceFormat != null)
sourceName = SourceFormat.Invoke(sourceName);
return CacheToolProvider?.Invoke(sourceName) ?? DefaultCacheTool;
}
#region 缓存添加
///
/// 添加滚动过期缓存,如果存在则更新
///
/// 添加缓存对象类型
/// 添加对象的key
/// 值
/// 滚动过期时长,访问后自动延长
/// 来源名称
/// 是否添加成功
public static Task SetAsync(string key, T obj, TimeSpan slidingExpiration, string sourceName = "")
{
return SetAsync(key, obj,new CacheTimeOptions(){sliding_expiration = slidingExpiration }, sourceName);
}
///
/// 添加固定过期时间缓存,如果存在则更新
///
/// 添加缓存对象类型
/// 添加对象的key
/// 值
/// 固定过期时长,设置后到时过期
/// 来源名称
/// 是否添加成功
public static Task SetAbsoluteAsync(string key, T obj, TimeSpan absoluteExpiration, string sourceName = "")
{
return SetAsync(key, obj, new CacheTimeOptions(){absolute_expiration_relative_to_now = absoluteExpiration}, sourceName);
}
///
/// 设置缓存
///
///
/// 添加对象的key
/// 值
/// 缓存过期时间选项
///
///
public static Task SetAsync(string key, T obj, CacheTimeOptions opt, string sourceName = "")
{
return GetCache(sourceName).SetAsync(key, obj, opt);
}
#endregion
#region 缓存获取(简单)
///
/// 获取缓存对象
///
/// 获取缓存对象类型
/// key
/// 来源名称
/// 获取指定key对应的值
public static Task GetAsync(string key, string sourceName = "")
{
return GetCache(sourceName).GetAsync(key);
}
#endregion
#region 缓存获取(击穿保护)
///
/// 获取缓存数据,如果没有则添加
///
///
/// key
/// 获取原始数据方法
/// 滚动过期时长,访问后自动延长
/// 缓存击穿保护秒数,默认值10。
/// 来源名称
///
public static Task GetOrSetAsync(string cacheKey, Func> getFunc,
TimeSpan slidingExpiration, int hitProtectedSeconds = 10, string sourceName = "")
{
return GetOrSetAsync(cacheKey, getFunc, new CacheTimeOptions() { sliding_expiration = slidingExpiration }, null, hitProtectedSeconds, sourceName);
}
///
/// 获取缓存数据【同时添加缓存击穿保护】,如果没有则添加
///
///
/// key
/// 获取原始数据方法
/// 滚动过期时长,访问后自动延长
/// 设置缓存前验证原始数据,false - 不满足设置缓存条件(会触发验证缓存击穿保护), true - 满足设置缓存条件
/// 缓存击穿保护秒数,默认值10。
/// 来源名称
///
public static Task GetOrSetAsync(string cacheKey, Func> getFunc,TimeSpan slidingExpiration,
Func? beforeSettingChecker, int hitProtectedSeconds = 10,
string sourceName = "")
{
return GetOrSetAsync(cacheKey, getFunc,new CacheTimeOptions(){sliding_expiration = slidingExpiration}, beforeSettingChecker, hitProtectedSeconds, sourceName);
}
///
/// 获取缓存数据【同时添加缓存击穿保护】,如果没有则添加
///
///
/// key
/// 获取原始数据方法
/// 固定过期时长,设置后到时过期
/// 缓存击穿保护秒数,默认值10。
/// 来源名称
///
public static Task GetOrSetAbsoluteAsync(string cacheKey, Func> getFunc, TimeSpan absoluteExpiration, int hitProtectedSeconds = 10, string sourceName = "")
{
return GetOrSetAsync(cacheKey, getFunc, new CacheTimeOptions() { absolute_expiration_relative_to_now = absoluteExpiration }, null
, hitProtectedSeconds, sourceName);
}
///
/// 获取缓存数据【同时添加缓存击穿保护】,如果没有则添加
///
///
/// key
/// 获取原始数据方法
/// 固定过期时长,设置后到时过期
/// 设置缓存前验证原始数据,false - 不满足设置缓存条件(会触发验证缓存击穿保护), true - 满足设置缓存条件
/// 缓存击穿保护秒数,默认值10。
/// 来源名称
///
public static Task GetOrSetAbsoluteAsync(string cacheKey, Func> getFunc,TimeSpan absoluteExpiration,
Func? beforeSettingChecker, int hitProtectedSeconds = 10,string sourceName = "")
{
return GetOrSetAsync(cacheKey, getFunc, new CacheTimeOptions(){absolute_expiration_relative_to_now = absoluteExpiration}, beforeSettingChecker, hitProtectedSeconds, sourceName);
}
///
/// 获取缓存数据,如果没有则添加
///
/// 数据类型
///
/// 获取原始数据方法
/// 缓存时间信息
/// 设置缓存前验证原始数据,false - 不满足设置缓存条件(会触发验证缓存击穿保护), true - 满足设置缓存条件
/// 缓存击穿保护秒数,默认值10。
/// 来源名称
///
public static async Task GetOrSetAsync(string cacheKey, Func> getFunc, CacheTimeOptions cacheTimeOpt,
Func? beforeSettingChecker = null, int hitProtectedSeconds = 10, string sourceName = "")
{
if (getFunc == null)
throw new ArgumentNullException("获取原始数据方法(getFunc)不能为空!");
var isProtected = hitProtectedSeconds > 0;
if (isProtected)
{
var obj = await GetAsync>(cacheKey, sourceName);
if (obj != null)
return obj.data;
}
else
{
var obj = await GetAsync(cacheKey, sourceName);
if (obj != null && !obj.Equals(default(RType)))
return obj;
}
var data = await getFunc();
var checkRes = beforeSettingChecker == null ? (data != null && !data.Equals(default)) : beforeSettingChecker.Invoke(data);
if (isProtected)
{
if (!checkRes)
{
cacheTimeOpt = new CacheTimeOptions()
{
absolute_expiration_relative_to_now = TimeSpan.FromSeconds(hitProtectedSeconds)
};
}
var cacheData = new ProtectCacheData(data);
await SetAsync(cacheKey, cacheData, cacheTimeOpt, sourceName);
return data;
}
if (checkRes)
{
await SetAsync(cacheKey, data, cacheTimeOpt, sourceName);
}
return data;
}
#endregion
///
/// 移除缓存对象
///
///
/// 来源名称
/// 是否成功
public static Task RemoveAsync(string key, string sourceName = "")
{
return GetCache(sourceName).RemoveAsync(key);
}
///
/// 移除缓存对象
///
///
/// 来源名称
/// 是否成功
public static Task RemoveAsync(string[] keys, string sourceName = "")
{
return GetCache(sourceName).RemoveAsync(keys);
}
#region 过时方法
///
/// 获取缓存对象
///
/// 获取缓存对象类型
/// key
/// 来源名称
/// 获取指定key对应的值
[Obsolete("请使用 GetAsync")]
public static T Get(string key, string sourceName = "")
{
return GetAsync(key, sourceName).Result;
}
[Obsolete("请使用 RemoveAsync")]
public static bool Remove(string key, string sourceName = "")
{
return RemoveAsync(key,sourceName).Result;
}
///
/// 添加滚动过期缓存,如果存在则更新
///
/// 添加缓存对象类型
/// 添加对象的key
/// 值
/// 滚动过期时长,访问后自动延长
/// 来源名称
/// 是否添加成功
[Obsolete("请使用 SetAsync")]
public static bool Set(string key, T obj, TimeSpan slidingExpiration, string sourceName = "")
{
return SetAsync(key, obj, slidingExpiration, sourceName).Result;
}
///
/// 添加固定过期时间缓存,如果存在则更新
///
/// 添加缓存对象类型
/// 添加对象的key
/// 值
/// 固定过期时长,设置后到时过期
/// 来源名称
/// 是否添加成功
[Obsolete("请使用 SetAbsoluteAsync")]
public static bool Set(string key, T obj, DateTime absoluteExpiration, string sourceName = "")
{
return SetAbsoluteAsync(key, obj, TimeSpan.FromTicks((absoluteExpiration - DateTime.Now).Ticks), sourceName).Result;
}
#region 缓存获取
///
/// 获取缓存数据,如果没有则添加
///
///
/// key
/// 如果不存在,通过此方法获取原始数据添加缓存
/// 滚动过期时长,访问后自动延长
/// 来源名称
///
[Obsolete]
public static Task GetOrSetAsync(string cacheKey, Func> getFunc,
TimeSpan slidingExpiration, string sourceName)
{
return GetOrSetAsync(cacheKey, getFunc, new CacheTimeOptions() { sliding_expiration = slidingExpiration }
, sourceName);
}
///
/// 获取缓存数据,如果没有则添加
///
///
/// key
/// 没有数据时,通过此方法获取原始数据
/// 固定过期时长,设置后到时过期
/// 来源名称
///
[Obsolete]
public static Task GetOrSetAbsoluteAsync(string cacheKey, Func> getFunc,
TimeSpan absoluteExpiration, string sourceName)
{
return GetOrSetAsync(cacheKey, getFunc, new CacheTimeOptions()
{
absolute_expiration_relative_to_now = absoluteExpiration
}, sourceName);
}
///
/// 获取缓存数据,如果没有则添加
///
///
///
/// 没有数据时,通过此方法获取原始数据
///
/// 来源名称
///
[Obsolete]
public static async Task GetOrSetAsync(string cacheKey, Func> createFunc, CacheTimeOptions opt, string sourceName )
{
var obj = await GetAsync(cacheKey, sourceName);
if (obj != null && !obj.Equals(default(RType)))
return obj;
if (createFunc == null)
return default;
var data = await createFunc.Invoke();
if (data == null || data.Equals(default(RType)))
return data;
await SetAsync(cacheKey, data, opt, sourceName);
return data;
}
#endregion
#endregion
}
internal class ProtectCacheData
{
public ProtectCacheData(TT data)
{
this.data = data;
}
public TT data { get; }
}
}