using Castle.DynamicProxy;
using Newtonsoft.Json;
using SqlSugar;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using System.Text;
using System.Threading.Tasks;
using WIDESEAWCS_Core.Attributes;
using WIDESEAWCS_Core.Caches;
using WIDESEAWCS_Core.Helper;
using ICacheService = WIDESEAWCS_Core.Caches.ICacheService;
namespace WIDESEAWCS_Core.AOP
{
public class CacheAOP : IInterceptor
{
private readonly ICacheService _cacheService;
public CacheAOP(ICacheService cacheService)
{
_cacheService = cacheService;
}
public void Intercept(IInvocation invocation)
{
var method = invocation.MethodInvocationTarget ?? invocation.Method;
var cacheAttribute = method.GetCustomAttributes(true).FirstOrDefault(x => x.GetType() == typeof(CacheAttribute));
if (cacheAttribute is CacheAttribute qCachingAttribute)
{
//获取自定义缓存键
var cacheKey = CustomCacheKey(invocation);
if (_cacheService.Exists(cacheKey))
{
//将当前获取到的缓存值,赋值给当前执行方法
Type returnType;
if (typeof(Task).IsAssignableFrom(method.ReturnType))
{
returnType = method.ReturnType.GenericTypeArguments.FirstOrDefault();
}
else
{
returnType = method.ReturnType;
}
//根据key获取相应的缓存值
dynamic? cacheValue = _cacheService.Get(returnType, cacheKey);
if (cacheValue != null)
invocation.ReturnValue = (typeof(Task).IsAssignableFrom(method.ReturnType)) ? Task.FromResult(cacheValue) : cacheValue;
return;
}
//去执行当前的方法
invocation.Proceed();
//存入缓存
if (!string.IsNullOrWhiteSpace(cacheKey))
{
object response;
//Type type = invocation.ReturnValue?.GetType();
var type = invocation.Method.ReturnType;
if (typeof(Task).IsAssignableFrom(type))
{
dynamic result = invocation.ReturnValue;
response = result.Result;
}
else
{
response = invocation.ReturnValue;
}
if (response == null) response = string.Empty;
_cacheService.AddOrUpdate(cacheKey, response.Serialize(), qCachingAttribute.AbsoluteExpiration * 60);
}
}
else
{
invocation.Proceed(); //直接执行被拦截方法
}
}
///
/// 自定义缓存的key
///
///
///
protected string CustomCacheKey(IInvocation invocation)
{
var typeName = invocation.TargetType.Name;
//获取调用目标类型名称
var methodName = invocation.Method.Name;
//获取调用方法名称
var methodArguments = invocation.Arguments.Select(GetArgumentValue).Take(3).ToList();//获取参数列表,最多三个
string key = $"{typeName}:{methodName}:";
//定义key,格式为:类型名称:方法名称:
foreach (var param in methodArguments)
{
key = $"{key}{param}:";
//遍历参数列表,将参数值添加到key中,格式为:参数值:
}
return key.TrimEnd(':');
//返回key,去掉末尾的冒号
}
///
/// object 转 string
///
///
///
protected static string GetArgumentValue(object arg)
{
if (arg is DateTime)
// 如果arg是DateTime类型,则返回其字符串表示形式
return ((DateTime)arg).ToString("yyyyMMddHHmmss");
if (!arg.IsNotEmptyOrNull())
// 如果arg不是空或null,则返回其字符串表示形式
return arg.ObjToString();
if (arg != null)
{
// 如果arg不是空或null
if (arg is Expression)
{
// 如果arg是Expression类型
var obj = arg as Expression;
// 解析arg
var result = Resolve(obj);
// 返回MD5加密后的字符串
return MD5Helper.MD5Encrypt16(result);
}
else if (arg.GetType().IsClass)
{
// 如果arg是类类型
// 将arg序列化为JSON字符串
return MD5Helper.MD5Encrypt16(JsonConvert.SerializeObject(arg));
}
// 否则,返回"value:"加上arg的字符串表示形式
return $"value:{arg.ObjToString()}";
}
// 如果arg是空或null,则返回空字符串
return string.Empty;
}
private static string Resolve(Expression expression)
{
// 创建一个ExpressionContext对象
ExpressionContext expContext = new ExpressionContext();
// 解析表达式,并指定解析类型为WhereSingle
expContext.Resolve(expression, ResolveExpressType.WhereSingle);
// 获取解析结果
var value = expContext.Result.GetString();
// 获取参数列表
var pars = expContext.Parameters;
// 遍历参数列表
pars.ForEach(s =>
{
// 将参数名替换为参数值
value = value.Replace(s.ParameterName, s.Value.ObjToString());
});
// 返回替换后的值
return value;
}
}
}