C#使用 Attribute 实现 AOP 功能
2025-01-07
20
在 C# 中,通过自定义 Attribute 并结合一些技术(如动态代理、反射等)可以实现 AOP(面向切面编程)。AOP 通常用于日志记录、性能监控、权限验证等横切关注点。
以下是一个使用 C# Attribute 实现 AOP 功能的示例。假设我们要记录方法的执行时间:
步骤 1: 创建自定义 Attribute
定义一个继承自 Attribute 的类,用于标记目标方法。
[AttributeUsage(AttributeTargets.Method, Inherited = true)]
public class TimingAttribute : Attribute
{
}
步骤 2: 创建动态代理
使用动态代理在方法调用前后执行 AOP 功能。这里我们使用 DispatchProxy。
using System;
using System.Diagnostics;
public class AopProxy<T> : DispatchProxy
{
private T _target;
public void SetTarget(T target)
{
_target = target;
}
protected override object Invoke(MethodInfo targetMethod, object[] args)
{
var attribute = targetMethod.GetCustomAttribute<TimingAttribute>();
if (attribute != null)
{
// 方法带有 TimingAttribute,记录执行时间
var stopwatch = Stopwatch.StartNew();
Console.WriteLine($"开始执行方法: {targetMethod.Name}");
var result = targetMethod.Invoke(_target, args);
stopwatch.Stop();
Console.WriteLine($"方法 {targetMethod.Name} 执行完毕,耗时: {stopwatch.ElapsedMilliseconds}ms");
return result;
}
else
{
// 方法没有 TimingAttribute,直接调用
return targetMethod.Invoke(_target, args);
}
}
}
步骤 3: 使用代理生成增强类
创建一个工具类,用于生成代理对象。
public static class AopFactory
{
public static T Create<T>(T target)
{
var proxy = DispatchProxy.Create<T, AopProxy<T>>() as AopProxy<T>;
proxy.SetTarget(target);
return (T)proxy;
}
}
步骤 4: 定义业务逻辑类
创建一个需要应用 AOP 的业务类,并标记目标方法。
public class BusinessLogic
{
[Timing]
public void DoWork()
{
Console.WriteLine("正在执行业务逻辑...");
System.Threading.Thread.Sleep(1000); // 模拟耗时操作
}
public void NoTiming()
{
Console.WriteLine("没有 TimingAttribute 的方法");
}
}
步骤 5: 使用 AOP 代理
生成代理对象并调用方法。
class Program
{
static void Main(string[] args)
{
var business = new BusinessLogic();
var proxy = AopFactory.Create(business);
proxy.DoWork(); // 记录执行时间
proxy.NoTiming(); // 不记录执行时间
}
}
输出示例
开始执行方法: DoWork
正在执行业务逻辑...
方法 DoWork 执行完毕,耗时: 1002ms
没有 TimingAttribute 的方法
总结
Attribute 用于标记需要增强的方法。 DispatchProxy 用于拦截方法调用并注入逻辑。 动态代理的核心是反射和元数据分析。这种方式适用于轻量级 AOP 场景。如果需要更强大的功能,可以考虑使用成熟的 AOP 框架,如 PostSharp 或 AspectCore。
更新于:2天前赞一波!
相关文章
- .NET C# 使用Hook钩子实现全局监听键盘和鼠标
- .NET C#连接FTP实现文件上传下载
- C#中的线程安全的集合ConcurrentQueue使用示例
- .NET C#中的Func、Predicate和Expression用法详解
- C#13新特性 使用System.Threading.Lock简化线程同步
- .NET C# 读取编辑.AVIF图片文件
- .NET C# SkiaSharp读取.AVIF图片文件报错
- .NET C# EntityFramework(EF)连接SQLite代码示例
- .NET9 C# 13 有哪些新特性?
- C#中的String和StringBuilder的区别
- .NET C#中的IEnumerable和IEnumerator的区别
- C# Const 和 ReadOnly的区别
- C# 使用Barrier进行多线程同步
- C#发送邮件代码简洁示例(附源码下载)
- C# Word转换成Pdf的方法
- c#使用MongoDB开发LBS应用
- hprose for C#使用教程
- c#实现与Java无差异的GZip压缩和GZip解压缩
- Attribute特性封装通用数据验证
- .NET Core c#使用SkiaSharp压缩裁切图片去除水印
文章评论
评论问答