C#反射知识汇总

一、看清类型GetType(),GetProperties(),GetValue()

反射就是让程序在运行时认识“自己结构”的能力。

using System;
using System.Reflection;

public class Printer
{
    public static void PrintObject(object obj, int indent = 0)
    {
        if (obj == null)
        {
            Console.WriteLine(new string(' ', indent) + "null");
            return;
        }

        Type type = obj.GetType();

        // 只处理属性
        foreach (var prop in type.GetProperties())
        {
            var value = prop.GetValue(obj);

            // 格式化输出
            string output;
            if (value == null)
            {
                output = "null";
            }
            else if (value is string)
            {
                output = $"\"{value}\"";
            }
            else if (value.GetType().IsClass && value.GetType() != typeof(string))
            {
                // 递归打印复杂对象,一层缩进
                Console.WriteLine(new string(' ', indent) + $"{prop.Name}:");
                PrintObject(value, indent + 2);
                continue;
            }
            else
            {
                output = value.ToString();
            }

            Console.WriteLine(new string(' ', indent) + $"{prop.Name}: {output}");
        }
    }
}

// 测试类
public class Address
{
    public string City { get; set; }
    public string Street { get; set; }
}

public class User
{
    public string Name { get; set; }
    public int Age { get; set; }
    public Address Addr { get; set; }
}

class Program
{
    static void Main()
    {
        var user = new User
        {
            Name = "小浮",
            Age = 30,
            Addr = new Address { City = "北京", Street = "中关村" }
        };

        Printer.PrintObject(user);
    }
} 

输出

Name: "小浮"
Age: 30
Addr:
  City: "北京"
  Street: "中关村"

  

二、操作类型CreateInstance创建对象(就是反射版的new)、Invoke调用方法、Attribute读标签

动态创建对象、动态调用方法、访问私有成员、Attribute特性(给代码贴标签)

 

// 完整格式:类名, 程序集名
Type type = Type.GetType("MyApp.Models.User, MyApp.Models");

// 从配置或外部输入得到类名
string[] classNames = { "User", "Order" };

foreach (var name in classNames)
{
    Type type = Type.GetType(name);
    object obj = Activator.CreateInstance(type);//运行时按名字创建对象
    Console.WriteLine($"创建了: {obj.GetType().Name}");
}

  

Invoke不带参数

void RunPlugin(object plugin)
{
    Type type = plugin.GetType();

    // 找到名为 "Execute" 的方法
    MethodInfo method = type.GetMethod("Execute");

    // 调用它
    method.Invoke(plugin, null);//反射慢的原因:Invoke 的代价是性能——它需要在运行时检查参数类型、处理权限、做安全校验
}

  

Invoke带参数

public class MathTool
{
    public int Add(int a, int b) => a + b;
}

//使用
MathTool tool = new MathTool();
Type type = tool.GetType();

MethodInfo method = type.GetMethod("Add");

// 参数用 object 数组传入
object result = method.Invoke(tool, new object[] { 3, 5 });

Console.WriteLine((int)result);  // 输出: 8

  

 

public class BankAccount
{
    private decimal _balance = 1000m;
}

//使用
BankAccount account = new BankAccount();
Type type = account.GetType();

// BindingFlags 告诉反射"我要找什么样的成员"
FieldInfo field = type.GetField("_balance",
    BindingFlags.NonPublic | BindingFlags.Instance);

decimal balance = (decimal)field.GetValue(account);
Console.WriteLine(balance);  // 输出: 1000

  

Attribute特效:Attribute = 给代码打备注标签,运行时反射读取标签内容实现扩展逻辑;

[Description("用户姓名")]
public string Name { get; set; }

//也可自定义一个Attribute
[AttributeUsage(AttributeTargets.Property)]//AttributeTargets.Property这个标签只能贴在属性上
public class DescriptionAttribute : Attribute
{
    public string Text { get; }

    public DescriptionAttribute(string text)
    {
        Text = text;
    }
}
//使用
public class User
{
    [Description("用户姓名")]//命名惯例,省Attribute 
    public string Name { get; set; }

    [Description("用户年龄")]
    public int Age { get; set; }

    public string Password { get; set; }  // 没有标签
}

//用反射读取 Attribute
Type type = typeof(User);
foreach (var prop in type.GetProperties())
{
    var attr = prop.GetCustomAttribute<DescriptionAttribute>();

    if (attr != null)
        Console.WriteLine($"{prop.Name}: {attr.Text}");
    else
        Console.WriteLine($"{prop.Name}: (无描述)");
}

  

AttributeTargets可以附加到哪些元素上

AttributeTargets.Class       类
AttributeTargets.Method     方法
AttributeTargets.Property   属性
AttributeTargets.Field      字段
AttributeTargets.Parameter  参数
AttributeTargets.All        全部

  

三、优化

慢在这里:

type.GetMethod("Execute"):遍历当前类型所有方法,按名字匹配,遍历父类型(如果没有找到),检测重载。

object result = method.Invoke(tool, new object[] { 3, 5 });  //检查method是否为null、检查调用者有没有权限,检查参数是否匹配、参数类型装箱拆箱(invoke的参数和返回值都是object)。

可以用BenchmarkDotNet看代码差距

优化

1.缓存(非热路径)

// ✅ 好做法:缓存 MethodInfo
var method = typeof(MyType).GetMethod("Execute");

foreach (var item in list)
{
    method.Invoke(item, null);
}

  

2.表达式树(把反射编译成委托)

posted @ 2026-08-04 23:18  HelloWorld庄先生  阅读(4)  评论(0)    收藏  举报