-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathHybridCacheHandler.cs
More file actions
50 lines (43 loc) · 1.91 KB
/
HybridCacheHandler.cs
File metadata and controls
50 lines (43 loc) · 1.91 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
using System;
using System.Threading.Tasks;
using Microsoft.Extensions.Caching.Hybrid;
namespace ZibStack.NET.Aop;
/// <summary>
/// Built-in handler for <see cref="HybridCacheAttribute"/>. Caches method return values using
/// <see cref="Microsoft.Extensions.Caching.Hybrid.HybridCache"/> (L1 memory + optional L2 distributed cache).
///
/// <para>
/// This is an open generic handler — the source generator closes <c>T</c> with the method's
/// return type at compile time (e.g. <c>HybridCacheHandler<Product></c> for a method returning
/// <c>Task<Product></c>). This ensures <see cref="HybridCache"/> serializes and deserializes
/// the correct type.
/// </para>
///
/// <para>
/// Requires <c>Microsoft.Extensions.Caching.Hybrid</c> in DI. Works on async methods only
/// (<see cref="IAsyncAroundAspectHandler{T}"/>). For sync in-memory caching, use <see cref="CacheHandler"/>.
/// </para>
/// </summary>
public sealed class HybridCacheHandler<T> : IAsyncAroundAspectHandler<T>
{
private readonly HybridCache _cache;
public HybridCacheHandler(HybridCache cache) =>
_cache = cache ?? throw new ArgumentNullException(nameof(cache));
/// <inheritdoc />
public async ValueTask<T?> AroundAsync(AspectContext context, Func<ValueTask<T?>> proceed)
{
var duration = 300;
if (context.Properties.TryGetValue("DurationSeconds", out var ds) && ds is int d) duration = d;
var key = context.Properties.TryGetValue("__cacheKey", out var ck) && ck is string k
? k
: $"{context.ClassName}.{context.MethodName}({context.FormatParameters()})";
var options = new HybridCacheEntryOptions
{
Expiration = duration > 0 ? TimeSpan.FromSeconds(duration) : null,
};
return await _cache.GetOrCreateAsync(
key,
async _ => (await proceed().ConfigureAwait(false))!,
options).ConfigureAwait(false);
}
}