1
hutongqing
2024-10-29 9ca96199d92168fe221dda9aba56f55520a561d8
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
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(); //直接执行被拦截方法
            }
        }
 
        /// <summary>
        /// 自定义缓存的key
        /// </summary>
        /// <param name="invocation"></param>
        /// <returns></returns>
        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(':');
        }
 
        /// <summary>
        /// object 转 string
        /// </summary>
        /// <param name="arg"></param>
        /// <returns></returns>
        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;
        }
    }
}