优秀的编程知识分享平台

网站首页 > 技术文章 正文

从零开始使用特性(Attribute)在C#中实现AOP功能

nanyue 2025-02-19 13:18:48 技术文章 4 ℃

面向方面编程(Aspect-Oriented Programming,简称AOP)是一种编程范式,它通过分离横切关注点(如日志记录、事务管理、安全等)来提高代码的可维护性。AOP可以帮助我们将这些分散在各个模块中的横切关注点集中管理。本文将介绍如何使用C#中的特性(Attribute)来实现一个简单的AOP功能。

什么是特性?

C#特性(Attributes)允许你为代码中的各种元素(如类、方法、属性等)添加额外的数据。使用特性,你可以在声明这些元素时为它们添加元数据,这些元数据可以在运行时通过反射(Reflection)来访问和处理。

实现步骤

我们将通过以下几个步骤实现AOP:

  1. 创建一个自定义特性(Attribute)。
  2. 使用反射(Reflection)机制读取特性。
  3. 在方法执行前或后添加横切关注的逻辑(如日志记录)。

代码示例

第一步:创建一个自定义特性

首先,我们需要定义一个特性(Attribute)类。我们将创建一个名为 LogAttribute 的特性类,用于标记需要记录日志的方法。

using System;

[AttributeUsage(AttributeTargets.Method, Inherited = true)]
public class LogAttribute : Attribute
{
    // 其它业务
}

第二步:使用特性标记方法

接下来,在需要启用日志记录功能的方法上应用这个特性。

public class MyService
{
    [Log]
    public void Work()
    {
        Console.WriteLine("Doing work...");
    }

    [Log]
    public void Study()
    {
        Console.WriteLine("Doing study...");
    }
}

第三步:创建AOP逻辑

我们需要创建一个代理类(Proxy)来在方法执行前后添加日志记录逻辑。为了简化示例,我们将使用反射(Reflection)来动态调用标记了 LogAttribute 的方法。

public class LogProxy
{
    private readonly object _target;

    public LogProxy(object target)
    {
        _target = target;
    }

    public void Invoke(string methodName)
    {
        MethodInfo method = _target.GetType().GetMethod(methodName);
        if (method != null && method.GetCustomAttribute(typeof(LogAttribute)) != null)
        {
            Console.WriteLine($"[Log] Method {methodName} 进入");
            method.Invoke(_target, null);
            Console.WriteLine($"[Log] Method {methodName} 完成");
        }
        else if (method != null)
        {
            method.Invoke(_target, null);
        }
        else
        {
            throw new ArgumentException("Method not found", nameof(methodName));
        }
    }
}

第四步:使用代理类

现在,我们可以使用 LogProxy 来调用标记了 LogAttribute 的方法,并在执行前后记录日志。

public class Program
{
    public static void Main(string[] args)
    {
        MyService service = new MyService();
        LogProxy proxy = new LogProxy(service);

        // 调用有日志记录的方法
        proxy.Invoke("Work");
        
        proxy.Invoke("Study");
        
        // 若调用不存在的方法,会抛出异常
        // proxy.Invoke("NonExistentMethod");
    }
}

运行结果

运行上述代码时,你将看到如下输出:

小结

通过本文,我们展示了如何从零开始使用C#中的特性(Attribute)来实现一个简单的AOP功能。我们创建了一个自定义特性类 LogAttribute,并通过代理类 LogProxy 使用反射在方法执行前后添加日志记录的逻辑。尽管这个示例相当简单,但它提供了一个实现AOP的基本框架,你可以根据实际需求对其进行扩展和优化。

希望这篇文章对你理解和应用AOP有所帮助!

最近发表
标签列表