forked from anjoy8/Blog.Core
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathBlogRedisCacheAOP.cs
More file actions
134 lines (117 loc) · 4.88 KB
/
BlogRedisCacheAOP.cs
File metadata and controls
134 lines (117 loc) · 4.88 KB
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
using Blog.Core.Common;
using Castle.DynamicProxy;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
namespace Blog.Core.AOP
{
/// <summary>
/// 面向切面的缓存使用
/// </summary>
public class BlogRedisCacheAOP : IInterceptor
{
//通过注入的方式,把缓存操作接口通过构造函数注入
private IRedisCacheManager _cache;
public BlogRedisCacheAOP(IRedisCacheManager cache)
{
_cache = cache;
}
//Intercept方法是拦截的关键所在,也是IInterceptor接口中的唯一定义
public void Intercept(IInvocation invocation)
{
var method = invocation.MethodInvocationTarget ?? invocation.Method;
//对当前方法的特性验证
var qCachingAttribute = method.GetCustomAttributes(true).FirstOrDefault(x => x.GetType() == typeof(CachingAttribute)) as CachingAttribute;
if (qCachingAttribute != null)
{
//获取自定义缓存键
var cacheKey = CustomCacheKey(invocation);
//注意是 string 类型,方法GetValue
var cacheValue = _cache.GetValue(cacheKey);
if (cacheValue != null)
{
//将当前获取到的缓存值,赋值给当前执行方法
var type = invocation.Method.ReturnType;
var resultTypes = type.GenericTypeArguments;
if (type.FullName == "System.Void")
{
return;
}
object response;
if (type != null && typeof(Task).IsAssignableFrom(type))
{
//返回Task<T>
if (resultTypes.Count() > 0)
{
var resultType = resultTypes.FirstOrDefault();
// 核心1,直接获取 dynamic 类型
dynamic temp = Newtonsoft.Json.JsonConvert.DeserializeObject(cacheValue, resultType);
//dynamic temp = System.Convert.ChangeType(cacheValue, resultType);
// System.Convert.ChangeType(Task.FromResult(temp), type);
response = Task.FromResult(temp);
}
else
{
//Task 无返回方法 指定时间内不允许重新运行
response = Task.Yield();
}
}
else
{
// 核心2,要进行 ChangeType
response = System.Convert.ChangeType(_cache.Get<object>(cacheKey), type);
}
invocation.ReturnValue = response;
return;
}
//去执行当前的方法
invocation.Proceed();
//存入缓存
if (!string.IsNullOrWhiteSpace(cacheKey))
{
object response;
//Type type = invocation.ReturnValue?.GetType();
var type = invocation.Method.ReturnType;
if (type != null && typeof(Task).IsAssignableFrom(type))
{
var resultProperty = type.GetProperty("Result");
response = resultProperty.GetValue(invocation.ReturnValue);
}
else
{
response = invocation.ReturnValue;
}
if (response == null) response = string.Empty;
_cache.Set(cacheKey, response, TimeSpan.FromMinutes(qCachingAttribute.AbsoluteExpiration));
}
}
else
{
invocation.Proceed();//直接执行被拦截方法
}
}
//自定义缓存键
private 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 += $"{param}:";
}
return key.TrimEnd(':');
}
//object 转 string
private string GetArgumentValue(object arg)
{
if (arg is int || arg is long || arg is string)
return arg.ToString();
if (arg is DateTime)
return ((DateTime)arg).ToString("yyyyMMddHHmmss");
return "";
}
}
}