PostSharp 的 AuditAttribute 未生效的根本原因是编译时织入(CTI)未触发,因其依赖 MSBuild 在编译阶段修改 IL,而非运行时代理;需确认项目正确引用 PostSharp SDK、删除手动 Import、重新生成解决方案,并检查输出窗口是否有 PostSharp 织入日志。

PostSharp 的 AuditAttribute 为什么没生效?
根本原因通常是编译时织入(CTI)未触发——PostSharp 不是运行时代理,它依赖 MSBuild 在编译阶段修改 IL。如果你用的是 SDK 风格项目(.csproj),但没正确引用 PostSharp SDK,或者用了 .NET 6+ 的隐式 Using 全局命名空间,[Audit] 就只是个普通特性,不会织入任何逻辑。
实操建议:
- 确认
.csproj中包含(注意版本需匹配你的 .NET 版本,6.10.x 支持 .NET 6/7/8) - 删除自定义的
或手动添加的PostSharp.targets,新版 PostSharp 会自动注入 - 在类或方法上加
[Audit]后,务必重新生成整个解决方案(不是仅“生成”,而是“重新生成”),否则旧 IL 可能被缓存 - 检查输出窗口是否有类似
PostSharp: Entering post-compilation...的日志,没有则说明织入失败
如何让 AuditAttribute 拦截到参数和返回值?
PostSharp 的 OnMethodBoundaryAspect 默认不自动捕获参数值和返回值,因为它们可能不可序列化、含敏感数据,或影响性能。你必须显式读取并处理。
实操建议:
- 继承
OnMethodBoundaryAspect,重写OnEntry和OnExit - 在
OnEntry中通过args.MethodExecutionTag或直接访问args.Arguments获取参数;注意args.Arguments.GetArgument(0)是按索引取,不是按名称 - 在
OnExit中用args.ReturnValue获取返回值,但若方法是async Task,需先 await 或用args.TaskResult(PostSharp 6.10+ 支持) - 避免在
OnException中直接序列化异常对象(如ex.ToString()即可,别传ex实例),防止循环引用或跨域序列化失败
OnMethodBoundaryAspect 和 MethodInterceptionAspect 怎么选?
前者适合审计日志这类“旁路观察”,开销低、语义清晰;后者适合需要改写调用逻辑(比如缓存、重试、权限校验),但会引入额外委托调用,且无法在 OnInvoke 中直接拿到原始参数数组。
实操建议:
- 做审计日志优先用
OnMethodBoundaryAspect:它天然支持OnEntry/OnExit/OnException三阶段,日志时间点明确 - 如果必须修改参数(比如脱敏入参)或拦截 async 方法的中间状态,才考虑
MethodInterceptionAspect,但要注意它的args.Proceed()是同步调用,async 方法需用args.ProceedAsync() - 不要在
OnMethodBoundaryAspect的OnExit里 throw 新异常——这会覆盖原始异常,审计日志就看不到真实错误了
审计日志写到文件还是数据库?PostSharp 本身不关心,但你得防住线程和 IO
PostSharp 织入后的代码运行在线程池线程、ASP.NET Core 请求线程、甚至定时器线程中,而日志写入(尤其文件)是典型 IO 密集操作,容易成为瓶颈或引发死锁。
实操建议:
- 绝对不要在
OnEntry/OnExit里直接调用File.AppendAllText或同步 DB 插入——会阻塞当前执行线程 - 推荐用内存队列 + 后台服务模式:在切面中把日志对象发给
Channel或ConcurrentQueue,再由独立IHostedService批量刷盘 - 如果用 Serilog,确保配置了异步写入(
.WriteTo.Async(...)),并设置合理 buffer size,否则高并发下日志会堆积在内存 - 特别注意:ASP.NET Core 的
HttpContext在后台线程不可用,若需记录请求 ID 或用户信息,必须在OnEntry中提前提取并存入args.MethodExecutionTag
PostSharp 的织入发生在编译期,这意味着你在调试器里看不到“拦截代码”的断点——它已经变成 IL 里的跳转指令了。最容易被忽略的,是 Aspect 的构造函数不能依赖 DI 容器,所有外部依赖(比如日志器、配置)都得通过属性注入或静态工厂获取。










