using System;
namespace Dpz.Core.SourceGenerator.Attributes;
/// <summary>
/// 标记需要由源生成器生成缓存装饰器的实现方法。
/// </summary>
/// <remarks>
/// <para>
/// 该特性应标记在实现类的方法上,而不是接口方法上。接口只描述服务契约,
/// 是否缓存属于具体实现的策略。
/// </para>
/// <para>
/// 源生成器会根据实现类型、方法名和参数生成缓存键,并要求目标类型可以注入
/// <c>IFusionCache</c>。遇到暂不支持的参数类型时,请显式设置 <see cref="CacheKey" />,
/// 或将参数调整为可稳定格式化的类型。
/// </para>
/// </remarks>
[AttributeUsage(AttributeTargets.Method, Inherited = false)]
public sealed class CacheAttribute : Attribute
{
/// <summary>
/// 缓存键前缀。未设置时使用实现类型的完整名称。
/// </summary>
public string? Prefix { get; set; }
/// <summary>
/// 显式缓存键。设置后优先使用该值,不再根据参数拼接缓存键。
/// </summary>
public string? CacheKey { get; set; }
/// <summary>
/// 缓存过期时间,单位为秒,默认一小时。
/// </summary>
public int ExpirationSeconds { get; set; } = 3600;
/// <summary>
/// 缓存命中或新写入缓存后需要执行的后处理方法名称。
/// </summary>
/// <remarks>
/// 后处理方法必须定义在当前实现类上,并且能被生成的缓存装饰器访问。要求:
/// <list type="bullet">
/// <item>实例方法(非 static),返回 <c>Task</c>、<c>ValueTask</c>、<c>Task<T></c>
/// 或 <c>ValueTask<T></c>。</item>
/// <item>第一个参数类型必须与被缓存方法的返回值类型一致(即被缓存方法的
/// <c>Task<T></c> 中的 <c>T</c>)。</item>
/// <item>推荐使用 <c>internal</c> 可见性。</item>
/// </list>
/// 找不到匹配方法时,源生成器会输出 <c>DPZ_CACHE003</c> 编译错误。
/// </remarks>
public string? PostProcess { get; set; }
/// <summary>
/// 额外缓存标签,用于跨业务域或组合场景清理缓存。
/// </summary>
/// <remarks>
/// 源生成器始终会自动写入前缀标签和方法标签;这里只需要填写额外的业务标签。
/// </remarks>
public string[] AdditionalTags { get; set; } = [];
}
⚠⚠ 以下内容为AI分析的结果,请根据实际情况进行判断。
代码解释
这是一个用于源代码生成器(Source Generator)的特性(Attribute)类,用于标记需要自动生成缓存装饰器的方法。
核心功能
CacheAttribute 特性允许开发者在实现类的方法上标记,告诉源生成器为该方法自动生成缓存逻辑,使用 IFusionCache 作为缓存提供程序。
关键属性说明
1. Prefix(缓存键前缀)
public string? Prefix { get; set; }
- 用于自定义缓存键的前缀部分
- 未设置时默认使用实现类的完整类型名称
2. CacheKey(显式缓存键)
public string? CacheKey { get; set; }
- 直接指定完整的缓存键
- 设置后会忽略参数拼接,优先使用该值
- 适用于参数类型不支持自动格式化的场景
3. ExpirationSeconds(过期时间)
public int ExpirationSeconds { get; set; } = 3600;
- 缓存过期时间(秒)
- 默认值:3600秒(1小时)
4. PostProcess(后处理方法)
public string? PostProcess { get; set; }
- 指定缓存命中或写入后要执行的回调方法名
- 方法要求:
- 必须是实例方法(非静态)
- 返回类型:
Task、ValueTask、Task<T>或ValueTask<T> - 第一个参数类型必须与被缓存方法的返回值类型一致
- 推荐使用
internal访问级别
- 找不到匹配方法时会产生
DPZ_CACHE003编译错误
5. AdditionalTags(额外标签)
public string[] AdditionalTags { get; set; } = [];
- 用于缓存失效策略的业务标签
- 源生成器会自动添加前缀标签和方法标签
- 这里只需填写额外的业务域标签
使用场景示例
public class UserService
{
[Cache(ExpirationSeconds = 600, PostProcess = nameof(LogUserAccess))]
public async Task<User> GetUserByIdAsync(int userId)
{
// 实际查询逻辑
}
internal async Task LogUserAccess(User user)
{
// 后处理逻辑
}
}
设计要点
- 标记在实现类而非接口:缓存是实现策略,不是契约的一部分
- 依赖 IFusionCache:目标类必须能注入该缓存接口
- 类型限制:仅可用于方法,不可继承(
Inherited = false)
这个特性是声明式缓存的典型应用,通过元数据驱动代码生成,减少样板代码。
评论加载中...