c# 如何实现aop aop是什么

来源:这里教程网 时间:2026-02-21 17:35:50 作者:

AOP 不是 C# 语言原生支持的特性,也没有

attribute
interface
能直接“开启 AOP”——它是一种编程思想,落地到 C# 必须依赖第三方库或手动织入逻辑。

什么是 AOP?别被术语绕晕

AOP(Aspect-Oriented Programming,面向切面编程)本质就是把横切关注点(比如日志、权限校验、异常统一处理、性能计时)从主业务逻辑里抽出来,避免在每个方法开头/结尾重复写

Log.Info("enter")
if (!User.HasPermission()) throw...

它不替代 OOP,而是补位:OOP 拆的是“谁来做”,AOP 拆的是“什么时候额外做点什么”。

C# 里最常用且靠谱的 AOP 方案:Castle DynamicProxy

这是目前 .NET 生态中稳定、文档全、社区验证过的运行时代理方案。它通过继承(针对类)或实现接口(针对接口)动态生成代理类,在调用前后插入切面逻辑。

注意:它只对 虚方法(

virtual
)或接口方法 有效;
private
static
sealed
方法无法拦截。

安装包:
Install-Package Castle.Core
核心类型:
Castle.DynamicProxy.IInterceptor
Castle.DynamicProxy.ProxyGenerator
必须让目标类方法是
virtual
,或让目标对象实现某个接口并代理该接口
public class UserService
{
    public virtual void AddUser(string name) => Console.WriteLine($"Adding {name}");
}
<p>public class LoggingInterceptor : IInterceptor
{
public void Intercept(IInvocation invocation)
{
Console.WriteLine($"Before: {invocation.Method.Name}");
invocation.Proceed(); // 执行原方法
Console.WriteLine($"After: {invocation.Method.Name}");
}
}</p><p>// 使用
var generator = new ProxyGenerator();
var proxy = generator.CreateClassProxy<UserService>(new LoggingInterceptor());
proxy.AddUser("Alice"); // 输出 Before/After + Adding Alice

为什么不用 Attribute + Reflection 做 AOP?

有人尝试用自定义

[Log]
特性 + 反射遍历方法再调用,这看起来“纯原生”,但实际是伪 AOP:

调用链完全由你手写控制,不是透明代理,容易漏掉嵌套调用 无法获取真实调用上下文(如参数值、返回值、异常),
invocation.Arguments
这种结构根本不存在
性能差:每次都要反射解析特性、构造委托、捕获异常 不支持异步方法的
await
上下文穿透

换句话说:能跑,但不是 AOP;是手工 AOP 模拟器,维护成本高、边界 case 多、一升级就崩。

.NET 6+ 的新选择:源生成器(Source Generators)+ AOP 框架

CommunityToolkit.Mvvm
Fody
(需 MSBuild 集成)这类工具,能在编译期改 IL,实现无代理、无反射、零运行时开销的 AOP。

例如 Fody.PropertyChanged 插件,给属性加

[AlsoNotifyFor("FullName")]
,它就在编译时自动注入
OnPropertyChanged
调用——这才是真正“隐形”的切面。

但代价是:构建流程变重、调试困难、错误信息晦涩(报错在生成的 .g.cs 文件里)、和某些 SDK 冲突概率上升。

所以除非项目已重度依赖 Fody 或明确追求极致性能,否则 Castle DynamicProxy 仍是更稳妥的起点。

真正难的从来不是“怎么加日志”,而是决定哪些逻辑算“横切”、哪些该留在业务里;以及当

IInterceptor
里要访问
HttpContext
或数据库上下文时,如何安全传递生命周期作用域——这部分没标准答案,得看你的 DI 容器怎么配、代理怎么创建。

相关推荐