CloudGamingAdmin/admin-server/CloudGaming.Core.FreeRedis/Aop/Cache/FreeRedisCacheEvictAttribute.cs
2024-11-15 02:58:48 +08:00

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("前缀或尾缀匹配不可用!");
}
}
}