forked from 47-studio-org/PostSharp.Samples
-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathCacheAttribute.cs
72 lines (64 loc) · 2.43 KB
/
CacheAttribute.cs
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
using PostSharp.Aspects;
using PostSharp.Serialization;
using System.Runtime.Caching;
using System.Text;
namespace PostSharp.Samples.CustomCaching
{
/// <summary>
/// Custom attribute that, when applied to a method, caches the return value of the method according to parameter values.
/// </summary>
[PSerializable]
public sealed class CacheAttribute : OnMethodBoundaryAspect
{
/// <summary>
/// Method executed <i>before</i> the target method of the aspect.
/// </summary>
/// <param name="args">Method execution context.</param>
public override void OnEntry(MethodExecutionArgs args)
{
// Build the cache key.
var stringBuilder = new StringBuilder();
AppendCallInformation(args, stringBuilder);
var cacheKey = stringBuilder.ToString();
// Get the value from the cache.
var cachedValue = MemoryCache.Default.Get(cacheKey);
if (cachedValue != null)
{
// If the value is already in the cache, don't even execute the method. Set the return value from the cache and return immediately.
args.ReturnValue = cachedValue;
args.FlowBehavior = FlowBehavior.Return;
}
else
{
// If the value is not in the cache, continue with method execution, but store the cache key so we can reuse it when the method exits.
args.MethodExecutionTag = cacheKey;
args.FlowBehavior = FlowBehavior.Continue;
}
}
/// <summary>
/// Method executed <i>after</i> the target method of the aspect.
/// </summary>
/// <param name="args">Method execution context.</param>
public override void OnSuccess(MethodExecutionArgs args)
{
var cacheKey = (string) args.MethodExecutionTag;
MemoryCache.Default[cacheKey] = args.ReturnValue;
}
private static void AppendCallInformation(MethodExecutionArgs args, StringBuilder stringBuilder)
{
// Append type and method name.
var declaringType = args.Method.DeclaringType;
Formatter.AppendTypeName(stringBuilder, declaringType);
stringBuilder.Append('.');
stringBuilder.Append(args.Method.Name);
// Append generic arguments.
if (args.Method.IsGenericMethod)
{
var genericArguments = args.Method.GetGenericArguments();
Formatter.AppendGenericArguments(stringBuilder, genericArguments);
}
// Append arguments.
Formatter.AppendArguments(stringBuilder, args.Arguments);
}
}
}