203 lines
5.3 KiB
C#
203 lines
5.3 KiB
C#
namespace CloudGaming.Core.FreeRedis.Aop.Cache;
|
|
|
|
/// <summary>
|
|
/// 清除缓存AOP
|
|
/// </summary>
|
|
[AttributeUsage(AttributeTargets.Method, AllowMultiple = true, Inherited = true)]
|
|
public class FreeRedisCacheEvictAttribute : FreeRedisBaseCacheAttribute
|
|
{
|
|
private readonly Type _cacheClassType;
|
|
private readonly string _actionName;
|
|
|
|
public FreeRedisCacheEvictAttribute()
|
|
{
|
|
|
|
}
|
|
|
|
/// <summary>
|
|
/// 用于设置 默认 缓存key 需要 ,自动组合默认缓存名称
|
|
/// </summary>
|
|
/// <param name="cacheClassType">缓存 类 类型</param>
|
|
/// <param name="actionName">缓存函数名称</param>
|
|
public FreeRedisCacheEvictAttribute(Type cacheClassType, string actionName)
|
|
{
|
|
_cacheClassType = cacheClassType;
|
|
_actionName = actionName;
|
|
}
|
|
|
|
protected override string GetCacheKey(MethodContext context)
|
|
{
|
|
if (_cacheClassType != null && !string.IsNullOrWhiteSpace(_actionName))
|
|
{
|
|
return _cacheClassType?.FullName + "." + _actionName;
|
|
}
|
|
|
|
return base.GetCacheKey(context);
|
|
}
|
|
|
|
/// <summary>
|
|
/// 移除时机 默认方法执行完
|
|
/// </summary>
|
|
/// <value></value>
|
|
public bool BeforeRun { get; set; } = false;
|
|
|
|
|
|
public override void OnEntry(MethodContext context)
|
|
{
|
|
if (BeforeRun)
|
|
{
|
|
RemoveKey(context);
|
|
}
|
|
}
|
|
|
|
public override void OnException(MethodContext context)
|
|
{
|
|
|
|
}
|
|
|
|
public override void OnSuccess(MethodContext context)
|
|
{
|
|
|
|
}
|
|
|
|
public override void OnExit(MethodContext context)
|
|
{
|
|
if (!BeforeRun)
|
|
{
|
|
RemoveKey(context);
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// 移除key
|
|
/// </summary>
|
|
/// <param name="aopContext"></param>
|
|
private void RemoveKey(MethodContext aopContext)
|
|
{
|
|
if (!UseFreeRedis)
|
|
{
|
|
RemoveMemoryKey(aopContext);
|
|
}
|
|
else
|
|
{
|
|
RemoveRedisKey(aopContext);
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// 移除redis key
|
|
/// </summary>
|
|
/// <param name="aopContext"></param>
|
|
private void RemoveRedisKey(MethodContext aopContext)
|
|
{
|
|
var cacheKey = GetCacheKey(aopContext);
|
|
if (cacheKey.Contains('*'))
|
|
{
|
|
RemoveRedisGroupKey(aopContext, cacheKey);
|
|
}
|
|
else
|
|
{
|
|
var redisCache = GetDatabase(aopContext);
|
|
redisCache.Del(cacheKey);
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// 移除Redis分组的key
|
|
/// </summary>
|
|
/// <param name="aopContext"></param>
|
|
/// <param name="cacheKey"></param>
|
|
private void RemoveRedisGroupKey(MethodContext aopContext, string cacheKey)
|
|
{
|
|
List<string> redisKeys = new List<string>();
|
|
var redisCache = GetDatabase(aopContext);
|
|
foreach (var keys in redisCache.Scan(cacheKey, 10, null))
|
|
{
|
|
redisKeys.AddRange(keys);
|
|
}
|
|
|
|
redisCache.Del(redisKeys.ToArray());
|
|
}
|
|
|
|
/// <summary>
|
|
/// 移除内存key
|
|
/// </summary>
|
|
/// <param name="aopContext"></param>
|
|
private void RemoveMemoryKey(MethodContext aopContext)
|
|
{
|
|
var cacheKey = GetCacheKey(aopContext);
|
|
var cache = GetService<IMemoryCache>(aopContext);
|
|
|
|
// 是否要进行前缀或后缀匹配
|
|
if (cacheKey.StartsWith('*'))
|
|
{
|
|
var pattern = cacheKey.Substring(1, cacheKey.Length - 1);
|
|
RemoveMemoryGroupKey(pattern, cache, false);
|
|
}
|
|
else if (cacheKey.EndsWith('*'))
|
|
{
|
|
var pattern = cacheKey.Substring(0, cacheKey.Length - 1);
|
|
RemoveMemoryGroupKey(pattern, cache, true);
|
|
}
|
|
else
|
|
{
|
|
cache.Remove(cacheKey);
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// 移除内存缓存分组的 key
|
|
/// </summary>
|
|
/// <param name="pattern"></param>
|
|
/// <param name="memoryCache"></param>
|
|
/// <param name="isStart"></param>
|
|
private void RemoveMemoryGroupKey(string pattern, IMemoryCache memoryCache, bool isStart)
|
|
{
|
|
var entries = memoryCache.GetType().GetField("_entries", BindingFlags.Instance | BindingFlags.NonPublic)?.GetValue(memoryCache) as IDictionary;
|
|
if (entries != null)
|
|
{
|
|
List<string> keys = new List<string>();
|
|
|
|
if (isStart)
|
|
{
|
|
// 前缀模式匹配
|
|
foreach (var key in entries.Keys)
|
|
{
|
|
var k = key as string;
|
|
if (k != null)
|
|
{
|
|
if (k.StartsWith(pattern))
|
|
{
|
|
keys.Add(k);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// 尾缀模式匹配
|
|
foreach (var key in entries.Keys)
|
|
{
|
|
var k = key as string;
|
|
if (k != null)
|
|
{
|
|
if (k.EndsWith(pattern))
|
|
{
|
|
keys.Add(k);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
foreach (var key in keys)
|
|
{
|
|
memoryCache.Remove(key);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
throw new Exception("前缀或尾缀匹配不可用!");
|
|
}
|
|
}
|
|
|
|
} |