C# 特性(Attributes)是用于在运行时为程序元素(如类、方法、属性等)添加声明性信息的一种方式。这些信息可以在程序运行时通过反射(Reflection)访问。特性可以用来控制程序行为、添加元数据或者影响程序的运行时行为。
.Net 框架提供了两种类型的特性:预定义特性和自定义特性。
 
 用法如下:
#define DEBUG_PRINT
using System;
using System.Diagnostics;
class Test
{
    // 如果定义的 DEBUG_PRINT ,该函数可以执行;没有定义DEBUG_PRINT,该函数将无法执行
    [Conditional("DEBUG_PRINT")]
    static void function1()
    {
        Console.WriteLine("DEBUG_PRINT In Function 1.");
    }
    [Obsolete("Don't use OldMethod, use NewMethod instead", true)]
    public static void OldMethod()
    {
        Console.WriteLine("It is the old method");
    }
    public static void NewMethod()
    {
        Console.WriteLine("It is the new method");
    }
    public static void Main()
    {
        Console.WriteLine("Main");
        //OldMethod();  提示,Don't use OldMethod, use NewMethod instead
        function1();
    }
}
 
Conditional
Conditional类似于条件编译,在上面的程序中当预定义DEBUG_PRINT,那么运行时就会调用function1,预定义放到了代码文件的最上面:
#define DEBUG_PRINT
 
Obsolete
Obsolete表示舍弃,可用于警告提示。
自定义属性
MyCustomAttribute.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Attribute02
{
    [AttributeUsage(System.AttributeTargets.Class | System.AttributeTargets.Struct|
        System.AttributeTargets.Method)]
    internal class MyCustomAttribute : System.Attribute
    {
        private string description;
        private string returnType;
        // 在构造函数中指定属性信息
        public MyCustomAttribute(string desc, string returnType)
        {
            this.description = desc;
            this.returnType = returnType;
        }
        public string GetDescription()
        {
            return this.description;
        }
        public string GetReturnType()
        {
            return this.returnType;
        }
    }
}
 
使用MyCustomAttribute修饰类MyClass和它的成员方法GetSum
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Attribute02
{
    [MyCustomAttribute("This is a custom description", "Class No return")]
    internal class MyClass
    {
        [MyCustomAttribute("This is a custom description", "Method int return")]
        public int GetSum(int x, int y)
        {
            return x + y;
        }
    }
}
 
Main测试
namespace Attribute02
{
    internal class Program
    {
        static void Main(string[] args)
        {
            Console.WriteLine("测试自定义属性");
            // 反射出类的属性信息
            Type type = typeof(MyClass);
            object[] attributes = type.GetCustomAttributes(typeof(MyCustomAttribute), true);
            foreach (MyCustomAttribute attr in attributes)
            {
                Console.WriteLine(attr.GetDescription());
                Console.WriteLine(attr.GetReturnType());
            }
            // 反射出方法的属性信息
            var method = typeof(MyClass).GetMethod("GetSum");
            var attributesMethon = method.GetCustomAttributes(typeof(MyCustomAttribute), false);
            if (attributesMethon.Length > 0)
            {
                var myAttribute = (MyCustomAttribute)attributesMethon[0];
                Console.WriteLine(myAttribute.GetDescription());
                Console.WriteLine(myAttribute.GetReturnType());
            }
        }
    }
}
 
运行结果如下:
 测试自定义属性
 This is a custom description
 Class No return
 This is a custom description
 Method int return
自定义特性应用多个属性
在C#中,AttributeUsage 属性用来定义一个自定义属性可以应用到的程序元素,以及该属性是否可以多次应用和是否可以被继承。
 validOn它是枚举器 AttributeTargets 的值的组合。默认值是 AttributeTargets.All。用以指定特性可以应用到哪些程序元素(如类、结构、方法等)上。
[AttributeUsage(AttributeTargets.Class |
AttributeTargets.Constructor |
AttributeTargets.Field |
AttributeTargets.Method |
AttributeTargets.Property, 
AllowMultiple = true)]
 
AllowMultiple 参数是一个布尔值,指示是否可以对单一程序元素应用多个此类特性实例。
 Inherited 参数也是一个布尔值,指示特性是否可以被派生类继承。
 例如
namespace Attribute03
{
    // 定义一个自定义特性,可以应用于类和结构,可以被继承,并且允许多次应用
    [AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct, Inherited = true, AllowMultiple = true)]
    public class MyCustomAttribute : Attribute
    {
        public string Name { get; set; }
        public MyCustomAttribute(string name)
        {
            Name = name;
        }
    }
}
 
使用MyCustomAttribute修饰ExampleClass
namespace Attribute03
{
    // 应用自定义特性到一个类多次
    [MyCustomAttribute("ExampleClass")]
    [MyCustomAttribute("AnotherNameForTheSameClass")]
    public class ExampleClass
    {
        // 类的实现内容
    }
}
 
Main测试
namespace Attribute03
{
    internal class Program
    {
        static void Main(string[] args)
        {
            Console.WriteLine("Attribute03");
            // 通过反射获取特性信息
            var attributes = typeof(ExampleClass).GetCustomAttributes(typeof(MyCustomAttribute), true);
            foreach (MyCustomAttribute attr in attributes)
            {
                Console.WriteLine($"Class {typeof(ExampleClass).Name} has the custom attribute with name: {attr.Name}");
            }
        }
    }
}
 
其它用法
C# 特性Attribute除了用于添加元数据和通过反射检索信息之外,它们还可用于以下目的:
-  
控制程序行为:
- 编译器指令:特性可以用来给编译器提供指令,如 
[Obsolete]用于标记过时的代码元素。 - 条件编译:特性可用于条件编译,例如 
[Conditional("DEBUG")]可以使方法仅在 DEBUG 模式下编译和执行。 
 - 编译器指令:特性可以用来给编译器提供指令,如 
 -  
数据验证:
- 在数据模型中,特性经常用于验证数据。例如,在实体框架(Entity Framework)或数据注释(Data Annotations)中,你可以使用 
[Required],[StringLength]等特性来定义数据验证规则。 
 - 在数据模型中,特性经常用于验证数据。例如,在实体框架(Entity Framework)或数据注释(Data Annotations)中,你可以使用 
 -  
序列化和反序列化控制:
- 在数据序列化过程中,特性用于控制如何将对象转换为 XML 或 JSON 等格式。例如,
[Serializable]、[DataContract]和[DataMember]。 
 - 在数据序列化过程中,特性用于控制如何将对象转换为 XML 或 JSON 等格式。例如,
 -  
拦截器和动态代理:
- 在面向切面编程(AOP)中,特性用于定义方法拦截器。这在动态代理创建时特别有用,例如在 .NET Core 中的依赖注入(DI)。
 
 -  
声明性安全:
- 特性可用于定义安全要求,如 
[PrincipalPermission]用于声明方法执行所需的安全上下文。 
 - 特性可用于定义安全要求,如 
 -  
编写插件和扩展:
- 在插件架构中,特性可用于标识插件类或方法,便于动态加载和识别。
 
 -  
单元测试框架:
- 在单元测试中,特性用于标记测试方法和测试类(例如 
[TestMethod]或[TestClass]),以及进行测试设置和清理(如[TestInitialize]和[TestCleanup])。 
 - 在单元测试中,特性用于标记测试方法和测试类(例如 
 -  
依赖注入配置:
- 在依赖注入(DI)中,特性可以用于标记构造函数、属性或方法,以指导 DI 容器如何进行注入。
 
 -  
框架和库集成:
- 许多框架和库使用特性来集成与特定框架或库的功能,如 ASP.NET Core 中的路由、授权和过滤器特性(如 
[Route],[Authorize],[ActionFilter]等)。 
 - 许多框架和库使用特性来集成与特定框架或库的功能,如 ASP.NET Core 中的路由、授权和过滤器特性(如 
 
通过这些用途,C# 特性成为了一种强大的机制,可以在不改变代码本身逻辑的情况下丰富和扩展代码的功能。
代码如下:
1. 编译器指令([Obsolete] 特性)
 
public class MyClass
{
    [Obsolete("Use NewMethod instead", false)]  // 标记为过时
    public void OldMethod()
    {
        Console.WriteLine("This is the old method.");
    }
    public void NewMethod()
    {
        Console.WriteLine("This is the new method.");
    }
}
 
2. 数据验证(使用数据注释)
using System.ComponentModel.DataAnnotations;
public class User
{
    [Required]
    public string Name { get; set; }
    [StringLength(10, ErrorMessage = "ID cannot be longer than 10 characters.")]
    public string ID { get; set; }
}
 
3. 序列化和反序列化控制([Serializable] 和 [DataMember] 特性)
 
using System.Runtime.Serialization;
[Serializable]
public class Person
{
    public string Name { get; set; }
    [DataMember]
    public int Age { get; set; }
}
 
4. 面向切面编程(AOP)中的方法拦截器
public class LoggingAttribute : Attribute
{
    // 这里只是示例,实际的拦截实现需要结合拦截器框架使用
    public void BeforeCall() => Console.WriteLine("Before method call");
    public void AfterCall() => Console.WriteLine("After method call");
}
public class MyClass
{
    [Logging]
    public void MyMethod()
    {
        Console.WriteLine("Executing the method.");
    }
}
 
5. 声明性安全
using System.Security.Permissions;
public class SecureClass
{
    [PrincipalPermission(SecurityAction.Demand, Role = "Administrator")]
    public void SecureMethod()
    {
        Console.WriteLine("This method requires the Administrator role.");
    }
}
 
6. 插件和扩展标识
public class PluginAttribute : Attribute
{
    public string Name { get; set; }
}
[Plugin(Name = "MyPlugin")]
public class MyPlugin
{
    // 插件的实现
}
 
7. 单元测试
using Microsoft.VisualStudio.TestTools.UnitTesting;
[TestClass]
public class MyTestClass
{
    [TestMethod]
    public void MyTestMethod()
    {
        // 测试代码
    }
}
 
8. 依赖注入配置
public class MyService
{
    [Inject]
    public IDependency MyDependency { get; set; }
    // 假设 Inject 是一个标记依赖注入的特性
}
 
9. 框架和库集成
using Microsoft.AspNetCore.Mvc;
public class MyController : Controller
{
    [Route("api/myroute")]
    public IActionResult MyAction()
    {
        return Ok();
    }
}
 
以上代码示例涵盖了特性在 C# 中的各种不同用途,展示了特性如何被应用于实际编程场景中。





![BUUCTF [BJDCTF2020]just_a_rar 1](https://img-blog.csdnimg.cn/8febabcc793e4143938fc9223395ea50.png)













