雷达智富

首页 > 内容 > 程序笔记 > 正文

程序笔记

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天前
赞一波!

文章评论

评论问答