csharp 反射

csharp 特性

  1. 特性语法就是用方括号 [ ] 给代码添加元数据,让编译器或框架根据这些标签执行额外行为.
using System;
using System.Reflection;
using System.Linq;

// 自定义特性1: 作者信息特性
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, AllowMultiple = true)]
public class AuthorAttribute : Attribute
{
    public string Name { get; set; }
    public string Date { get; set; }

    public AuthorAttribute(string name, string date)
    {
        Name = name;
        Date = date;
    }
}

// 自定义特性2: 版本特性
[AttributeUsage(AttributeTargets.Class, AllowMultiple = true)]
public class VersionAttribute : Attribute
{
    public string Version { get; set; }
    public string? Description { get; set; }

    public VersionAttribute(string version)
    {
        Version = version;
    }
}

// 自定义特性3: 必填字段特性
[AttributeUsage(AttributeTargets.Property)]
public class RequiredAttribute : Attribute
{
    public string ErrorMessage { get; set; }

    public RequiredAttribute(string errorMessage = "此字段为必填项")
    {
        ErrorMessage = errorMessage;
    }
}

// 使用特性的示例类
[Author("张三", "2026-01-16")]
[Version("1.0")]
[Version("1.1")] // 需要设置 AllowMultiple = true 才能多次使用
public class User
{
    [Required("用户名不能为空")]
    public string? Username { get; set; }

    [Required("邮箱不能为空")]
    public string? Email { get; set; }

    public int Age { get; set; }

    [Author("李四", "2026-01-15")]
    public void PrintInfo()
    {
        Console.WriteLine($"用户名: {Username}, 邮箱: {Email}, 年龄: {Age}");
    }
}

// 程序入口
class Program
{
    static void Main(string[] args)
    {
        Console.OutputEncoding = System.Text.Encoding.UTF8;
        
        Console.WriteLine("=== C# 特性(Attributes)示例程序 ===\n");

        // 1. 读取类上的特性
        Console.WriteLine("【1】读取 User 类上的特性:");
        ReadClassAttributes(typeof(User));

        Console.WriteLine("\n【2】读取属性上的特性:");
        ReadPropertyAttributes(typeof(User));

        Console.WriteLine("\n【3】读取方法上的特性:");
        ReadMethodAttributes(typeof(User));

        Console.WriteLine("\n【4】验证对象属性:");
        ValidateObject();

        Console.WriteLine("\n【5】使用内置特性示例:");
        ShowBuiltInAttributes();
    }

    // 读取类上的特性
    static void ReadClassAttributes(Type type)
    {
        // 读取 AuthorAttribute
        var authorAttr = type.GetCustomAttribute<AuthorAttribute>();
        if (authorAttr != null)
        {
            Console.WriteLine($"  作者: {authorAttr.Name}, 日期: {authorAttr.Date}");
        }

        // 读取 VersionAttribute(可能有多个)
        var versionAttrs = type.GetCustomAttributes<VersionAttribute>();
        foreach (var attr in versionAttrs)
        {
            Console.WriteLine($"  版本: {attr.Version}");
        }
    }

    // 读取属性上的特性
    static void ReadPropertyAttributes(Type type)
    {
        var properties = type.GetProperties();
        foreach (var prop in properties)
        {
            var requiredAttr = prop.GetCustomAttribute<RequiredAttribute>();
            if (requiredAttr != null)
            {
                Console.WriteLine($"  属性 '{prop.Name}': {requiredAttr.ErrorMessage}");
            }
        }
    }

    // 读取方法上的特性
    static void ReadMethodAttributes(Type type)
    {
        var methods = type.GetMethods(BindingFlags.DeclaredOnly | BindingFlags.Public | BindingFlags.Instance);
        foreach (var method in methods)
        {
            var authorAttr = method.GetCustomAttribute<AuthorAttribute>();
            if (authorAttr != null)
            {
                Console.WriteLine($"  方法 '{method.Name}' - 作者: {authorAttr.Name}, 日期: {authorAttr.Date}");
            }
        }
    }

    // 验证对象(根据 Required 特性)
    static void ValidateObject()
    {
        var user = new User { Username = "", Email = "test@example.com", Age = 25 };
        var properties = typeof(User).GetProperties();
        bool isValid = true;

        foreach (var prop in properties)
        {
            var requiredAttr = prop.GetCustomAttribute<RequiredAttribute>();
            if (requiredAttr != null)
            {
                var value = prop.GetValue(user);
                if (value == null || (value is string && string.IsNullOrEmpty(value.ToString())))
                {
                    Console.WriteLine($"  ✗ 验证失败: {requiredAttr.ErrorMessage}");
                    isValid = false;
                }
                else
                {
                    Console.WriteLine($"  ✓ {prop.Name} 验证通过");
                }
            }
        }

        Console.WriteLine($"\n  整体验证结果: {(isValid ? "通过" : "失败")}");
    }

    // 演示内置特性
    static void ShowBuiltInAttributes()
    {
        var type = typeof(User);

        // Obsolete 特性示例
        Console.WriteLine($"  类型 '{type.Name}' 完全限定名: {type.FullName}");
        Console.WriteLine($"  程序集: {type.Assembly.GetName().Name}");

        // 检查是否标记了 Serializable
        var isSerializable = type.GetCustomAttribute<SerializableAttribute>() != null;
        Console.WriteLine($"  是否可序列化: {isSerializable}");
    }
}

// === C# 特性(Attributes)示例程序 ===

// 【1】读取 User 类上的特性:
//   作者: 张三, 日期: 2026-01-16
//   版本: 1.0
//   版本: 1.1

// 【2】读取属性上的特性:
//   属性 'Username': 用户名不能为空
//   属性 'Email': 邮箱不能为空

// 【3】读取方法上的特性:
//   方法 'PrintInfo' - 作者: 李四, 日期: 2026-01-15

// 【4】验证对象属性:
//   ✗ 验证失败: 用户名不能为空
//   ✓ Email 验证通过

//   整体验证结果: 失败

// 【5】使用内置特性示例:
//   类型 'User' 完全限定名: User
//   程序集: TestApp
//   是否可序列化: False

参考链接

1.C#反射