namespace CloudGaming.Core.FreeRedis.Aop.Cache;
[AttributeUsage(AttributeTargets.Method, AllowMultiple = true, Inherited = true)]
public abstract class FreeRedisBaseCacheAttribute : AopMoAttribute
{
///
/// 缓存Key 不填默认是 函数的命名空间.函数名称
///
///
public string? CacheKey { get; set; }
///
/// Redis 服务类型 不传递默认 走内存缓存
///
///
public bool UseFreeRedis { get; set; } = false;
///
/// 获取缓存Key
///
///
///
protected virtual string GetCacheKey(MethodContext context)
{
if (!string.IsNullOrWhiteSpace(CacheKey))
{
return ParseCacheKey(context);
}
var name = context.Method.Name;
var prefix = context.Method.DeclaringType?.FullName;
return $"{prefix}.{name}";
}
///
/// 解析缓存主键
///
/// 拦截器上下文
private string ParseCacheKey(MethodContext context)
{
//寻找大括号{} 内的内容
var replaceParameters = Regex.Matches(CacheKey, @"\{(.+?)\}").Select(m => m.Groups[1].Value).ToList();
if (replaceParameters.Count > 0)
{
// 获取所有方法参数
var typeNames = context.Method.GetParameters().Select(t => t.Name).ToList();
foreach (var replaceParameter in replaceParameters)
{
var firstName = replaceParameter.Split(".")[0];
// 查询括号里的内容 .分割后第一位 能和参数名对的上吗
if (typeNames.Contains(firstName))
{
// 获取这个值对应的索引
int index = typeNames.FindIndex(tname => tname == firstName);
// 对内容进行分割
var names = replaceParameter.Split(".").ToList();
// 分割后大于长度大于一 说明存在实例内部属性调用
if (names.Count > 1)
{
var replaceName = "{" + replaceParameter + "}";
// 移除第一位
names.RemoveAt(0);
// 递归获取到属性值
var value = GetParameterValue(context.Arguments[index], names);
value = value ?? "null";
CacheKey = CacheKey.Replace(replaceName, value);
}
else
{
var replaceName = "{" + replaceParameter + "}";
var value = context.Arguments[index]?.ToString();
CacheKey = CacheKey.Replace(replaceName, value);
}
}
}
}
return CacheKey;
}
///
/// 递归获取属性值
///
///
///
///
private string? GetParameterValue(object obj, List parameterNames)
{
if (obj == null)
{
return null;
}
if (parameterNames.Count > 1)
{
var name = parameterNames[0];
parameterNames.RemoveAt(0);
// 获取属性值
var propertyInfo = GetPropertyInfo(obj, name);
if (propertyInfo != null)
{
var val = propertyInfo.GetValue(obj);
if (val is null)
{
return default;
}
return GetParameterValue(val, parameterNames);
}
return null;
}
else if (parameterNames.Count == 1)
{
// 获取属性值
var propertyInfo = GetPropertyInfo(obj, parameterNames[0]);
// 从对象里获取这个属性
return propertyInfo?.GetValue(obj)?.ToString();
}
else
{
return null;
}
}
///
/// 根据属性名称获取实例里的属性
///
/// 实例
/// 需要的属性名
///
private PropertyInfo? GetPropertyInfo(object obj, string name)
{
if (obj == null)
{
return null;
}
// 获取所有public属性和实例
var propertyInfos = obj.GetType().GetProperties(BindingFlags.Instance | BindingFlags.Public);
// 找找有没有我们要的
return propertyInfos.FirstOrDefault(p => p.Name == name);
}
///
/// 获取Redis数据库
///
///
///
protected RedisClient GetDatabase(MethodContext MethodContext)
{
var redisService = GetService(MethodContext, typeof(RedisClient));
if (redisService == null)
{
throw new Exception($"请导入启动器 {nameof(CoreFreeRedisStartup)} ");
}
return redisService as RedisClient ?? throw new Exception("对象 RedisClient 转化失败!");
}
}