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}:";
foreach (var param in methodArguments)
{
key = $"{key}{param}:";
}
return key.TrimEnd(':');
}
///
/// object 转 string
///
///
///
protected static string GetArgumentValue(object arg)
{
if (arg is DateTime)
return ((DateTime)arg).ToString("yyyyMMddHHmmss");
if (!arg.IsNotEmptyOrNull())
return arg.ObjToString();
if (arg != null)
{
if (arg is Expression)
{
var obj = arg as Expression;
var result = Resolve(obj);
return MD5Helper.MD5Encrypt16(result);
}
else if (arg.GetType().IsClass)
{
return MD5Helper.MD5Encrypt16(JsonConvert.SerializeObject(arg));
}
return $"value:{arg.ObjToString()}";
}
return string.Empty;
}
private static string Resolve(Expression expression)
{
ExpressionContext expContext = new ExpressionContext();
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;
}
}
}