C# 特性(Attribute)

发布时间:2026/11/5 1:54:46
C# 特性(Attribute)

在 .NET Core 的开发体系中,特性(Attribute)不仅仅是一个简单的标签,更是实现声明式编程、解耦业务逻辑与基础设施代码的核心机制。无论是数据验证、API 路由控制,还是复杂的面向切面编程(AOP),特性都提供了高效的解决方案。

1. 特性 Attribute

特性

从本质上讲,特性是一种将元数据(Metadata)附加到代码元素(如类、方法、属性、参数等)上的机制。它不会直接改变代码的执行逻辑,而是为编译器或运行时提供额外的描述性信息。

理解为给代码打的“标签”或“注解”。例如:

  • [Required]告诉框架该字段不能为空。
  • [HttpGet]告诉 ASP.NET Core 该方法仅响应 GET 请求。
  • [Serializable]告诉序列化器该对象可以被序列化。

在没有引入特性之前,开发者往往需要通过大量的if-else或switch语句来处理诸如数据库映射、JSON 序列化、数据验证等逻辑。这导致代码紧密耦合,维护困难。

引入特性后,实现了‌声明式编程‌的优势:

  • ‌解耦‌:业务代码专注于核心逻辑,横切关注点(如日志、验证、权限)通过特性分离。
  • ‌统一规则‌:框架通过扫描特性自动执行相应逻辑,确保行为一致。
  • **简洁性无需编写繁琐的基础设施代码,只需添加标签即可生效。

2.自定义特性

虽然 .NET 提供了丰富的内置特性,但在实际开发中,我们常需要根据业务需求创建自定义特性例如实现特定的日志记录、权限校验或缓存策略。

创建自定义特性通常遵循以下步骤:

  • 创建一个继承自System.Attribute的类。
  • 使用AttributeUsage指定特性的适用目标(类、方法、属性等)。
  • 定义构造函数和属性以传递参数。

自定义日志特性

需要一个特性,用于标记需要记录详细执行日志的方法。

using System; // 1. 定义特性类 [AttributeUsage(AttributeTargets.Method, Inherited = false, AllowMultiple = false)] public class CustomLogAttribute : Attribute { public string Message { get; set; } public LogLevel Level { get; set; } = LogLevel.Information; public CustomLogAttribute(string message) { Message = message; } } public enum LogLevel { Information, Warning, Error }

使用自定义特性

public class OrderService { // 2. 应用特性 [CustomLog("开始处理订单创建", Level = LogLevel.Information)] public void CreateOrder(Order order) { // 业务逻辑 Console.WriteLine($"Order {order.Id} created."); } }

此时,CustomLogAttribute仅仅是一个元数据标记。若要使其真正生效(即执行日志记录逻辑),通常需要结合‌反射‌或‌AOP拦截器‌。

3.扩展 AOP 应用

特性本身不执行代码,必须配合拦截机制才能实现面向切面编程(AOP)。在 .NET Core 中,实现 AOP 的主流方式包括使用动态代理库(如 Castle DynamicProxy)或依赖注入容器的拦截扩展(如 Autofac)。

AOP 的核心思想

AOP旨在将横切关注点(如日志、事务、异常处理)从业务逻辑中剥离。当调用被特性标记的方法时,流程如下:

  • 调用方触发方法。
  • 代理对象拦截调用。
  • 执行前置逻辑(如记录开始时间、检查权限)。
  • 执行真实业务方法。
  • 执行后置逻辑(如记录结束时间、捕获异常)。

结合 Castle DynamicProxy 实现日志拦截

以下示例展示如何通过实现 `IInterceptor接口,读取自定义特性并执行日志记录。

定义拦截器

using Castle.DynamicProxy; using System.Reflection; public class LogInterceptor : IInterceptor { public void Intercept(IInvocation invocation) { // 1. 获取方法上的自定义特性 var method = invocation.MethodInvocationTarget; var logAttribute = method.GetCustomAttributes(typeof(CustomLogAttribute), true) .FirstOrDefault() as CustomLogAttribute; if (logAttribute != null) { // 2. 前置逻辑:记录开始 Console.WriteLine($"[LOG] {logAttribute.Message} - Start"); } try { // 3. 执行真实方法 invocation.Proceed(); } catch (Exception ex) { // 4. 异常处理 Console.WriteLine($"[ERROR] Exception occurred: {ex.Message}"); throw; } finally { if (logAttribute != null) { // 5. 后置逻辑:记录结束 Console.WriteLine($"[LOG] {logAttribute.Message} - End"); } } } }

创建代理并执行

var proxyGenerator = new ProxyGenerator(); var interceptor = new LogInterceptor(); // 创建 OrderService 的代理对象 var orderService = proxyGenerator.CreateClassProxy<OrderService>(interceptor); var order = new Order { Id = 1001 }; orderService.CreateOrder(order); // 输出结果: // [LOG] 开始处理订单创建 - Start // Order 1001 created. // [LOG] 开始处理订单创建 - End
  • Autofac + Castle DynamicProxy‌:在 ASP.NET Core 项目中,常替换默认 DI 容器为 Autofac,利用其 EnableInterfaceInterceptors 或 EnableClassInterceptors 功能,自动为注册的服务生成代理,无需手动创建 ProxyGenerator。
  • DispatchProxy‌:.NET Core 内置的轻量级代理类,适用于简单的场景,但功能不如 Castle DynamicProxy 强大。

4.常用内置特性分类

.NET Core 框架内置了大量特性,覆盖了 Web 开发、数据验证、依赖注入等多个领域。熟练掌握这些特性能极大提升开发效率。

API 与 MVC 控制

这些特性主要用于 ASP.NET Core Web API 和 MVC 控制器,定义路由、HTTP 方法和行为。

特性说明示例
[ApiController]标记控制器为 API 风格,启用自动模型验证和错误响应。[ApiController]
[Route]定义路由模板。[Route("api/[controller]")]
[HttpGet]/[HttpPost]指定允许的 HTTP 谓词。[HttpGet("{id}")]
[FromBody]指示参数从请求正文中绑定。public IActionResult Post([FromBody] User user)
[FromQuery]指示参数从查询字符串中绑定。public IActionResult Get([FromQuery] int page)

数据验证特性

主要用于 DTO(数据传输对象)或实体模型,配合模型验证中间件使用。

特性说明示例
[Required]字段不能为 null 或空。[Required(ErrorMessage = "姓名必填")]
[StringLength]限制字符串长度。[StringLength(100)]
[Range]限制数值范围。[Range(1, 120)]
[EmailAddress]验证邮箱格式。[EmailAddress]
[RegularExpression]使用正则表达式验证。[RegularExpression(@"^\d+$")]

数据实体特性 (Entity Framework Core)

用于配置数据库映射关系。

特性说明示例
[Key]指定主键。[Key]
[Table]指定对应的数据库表名。[Table("Users")]
[Column]指定列名或类型。[Column("user_name")]
[NotMapped]排除属性,不映射到数据库。[NotMapped]
[DatabaseGenerated]指定数据库生成策略(如自增)。[DatabaseGenerated(DatabaseGeneratedOption.Identity)]

依赖注入与服务生命周期

引入了直接标记服务生命周期的特性,简化了注册过程。

特性说明
[ServiceLifetime.Scoped]标记服务为 Scoped 生命周期。
[ServiceLifetime.Singleton]标记服务为 Singleton 生命周期。
[ServiceLifetime.Transient]标记服务为 Transient 生命周期。

PS:使用这些特性时,通常需要在程序启动时扫描程序集并自动注册服务。

安全与授权

特性说明
[Authorize]要求用户经过身份验证才能访问。
[AllowAnonymous]允许匿名访问,通常用于覆盖全局授权策略。
[ValidateAntiForgeryToken]防止跨站请求伪造攻击。

总结

特性(Attribute)是 .NET Core 生态中连接元数据与运行时行为的桥梁。

  • ‌理解本质‌:特性是元数据,需配合反射或拦截器才能产生实际效果。
  • ‌自定义扩展‌:通过继承Attribute类,可以轻松扩展业务所需的标记能力。
  • ‌AOP 实战‌:结合 Castle DynamicProxy 或 Autofac,利用特性实现日志、事务、权限等横切逻辑的自动化处理,显著提升代码的可维护性。
  • ‌善用内置‌:熟练掌握系统内置的特性,能够以更少的代码实现标准化的 Web 开发、数据验证和 ORM 映射。