C#基础——反射

C#基础——反射

C# 反射需要用到System.Reflection类完成。

准备工作

准备一个需要被拿来反射的类

class MyClass
{
    // 字段
    private string name;
    private int age;
    private bool sex;
    // 属性
    public string Name { get { return name; } set { name = value; } }
    public int Age { get { return age; } set { age = value; } }
    public bool Sex { get { return sex; } set { sex = value; } }
    // 无参构造器
    public MyClass(){}
    // 有参构造器
    public MyClass(string name,int age,bool sex) {
        Name = name;
        Age = age;
        Sex = sex;
    }
    public void print(string message)
    {
        Console.WriteLine("myclass:" + message);
    }
    public void print(string message, bool show)
    {
        if (show)
            Console.WriteLine("myclass:" + message);
    }
    public int add(int a, int b)
    {
        return a + b;
    }

    private int addAll(int[] arrs)
    {
        int val = 0;
        foreach (int item in arrs)
        {
            val += item;
        }
        return val;
    }
}

获取反射类

用类反射

Type type = typeof(MyClass);//用类反射

用字符串形式的全类名反射

Type type = Assembly.GetExecutingAssembly().GetType("ConsoleApp1.MyClass");

反射构造器

获取全部构造器

Type type = typeof(MyClass);//用类反射
ConstructorInfo[] constructorInfo = type.GetConstructors();

获取指定构造器

Type type = typeof(MyClass);
//其中的参数是指定构造器的参数类型数组
ConstructorInfo constructorInfo = type.GetConstructor(new Type[] { typeof(string),typeof(int),typeof(bool)});

反射字段

获取全部字段

方法GetFields不添加任何参数:获取public修饰的所有字段

Type type = typeof(MyClass);
// 获取类字段
FieldInfo[] fields = type.GetFields();
foreach (FieldInfo field in fields)
{
    Console.WriteLine($"字段名:{field.Name} 类型:{field.FieldType.FullName}");
}

获取指定字段

获取public修饰的字段,但为了保持代码的封装性,字段一般是不用public修饰字段。所以在获取字段的时候还需要加上要求——BindingFlags

Type type = typeof(MyClass);
// 第一个参数是字段名,第二个参数是“要求”
FieldInfo field =  type.GetField("name", BindingFlags.NonPublic | BindingFlags.Instance);

BindingFlags 是 C# 反射 API 中一个非常重要的枚举,它用于指定在反射操作中如何绑定到类型成员(如字段、属性、方法、构造函数等)。
这个枚举提供了一系列标志(flags),这些标志以按位或(bitwise OR)的方式组合起来,以指定反射操作的详细行为和范围。

以下是一些常用的 BindingFlags 标志及其描述:

  • Default:默认绑定标志,通常不直接使用,而是与其他标志组合使用。

  • IgnoreCase:在搜索类型成员时忽略大小写。

  • DeclaredOnly:仅搜索在当前类型上直接声明的成员,不搜索继承的成员。

  • Instance:指定搜索实例成员(非静态成员)。

  • Static:指定搜索静态成员。

  • Public:指定搜索公共成员。

  • NonPublic:指定搜索非公共成员(如 private、protected、internal 等)。

  • FlattenHierarchy:在搜索时,将层次结构中的成员视为在同一级别上。

  • InvokeMethod:用于调用方法。

  • GetField:用于获取字段的值。

  • SetField:用于设置字段的值。

  • GetProperty:用于获取属性的值。

  • SetProperty:用于设置属性的值。

  • CreateInstance:用于创建类的实例。

通过按位或操作符(|)组合这些标志,以满足特定的反射需求。例如,如果你想要搜索一个类的所有公共和非公共的静态字段,你可以使用
BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic

反射方法

获取public修饰的方法

using System.Reflection

Type type = typeof(MyClass);
MethodInfo[] methodInfo = type.GetMethods();//仅获取内部public修饰的方法

获取指定的private修饰的方法

MethodInfo field =  type.GetMethod("addAll", BindingFlags.NonPublic | BindingFlags.Instance,null,new Type[] { typeof(int[])},null);

获取指定的public修饰的方法

MethodInfo field = type.GetMethod("add");

获取方法参数信息

MethodInfo[] methodInfo = type.GetMethods();

foreach (MethodInfo item in methodInfo)
{
    // 获取方法名
    Console.WriteLine("方法名:" + item.Name);
    // 获取方法参数
    ParameterInfo[] parameterInfo = item.GetParameters();
    foreach (ParameterInfo param in parameterInfo)
    {
        // 获取方法参数类型
        Type paramType = param.ParameterType;
        // 获取参数名
        string paramName = param.Name;
        Console.WriteLine($"\t参数名:{paramName}\t类型:{paramType.FullName}");
    }
}

获取方法返回值信息

// 获取方法的返回值类型
Type backType = item.ReturnType;
Console.WriteLine($"\t返回值:{backType.Name}\t返回类型:{backType.FullName}\n");

反射属性

获取public修饰的全部属性

Type type = typeof(MyClass);
PropertyInfo[] attributes = type.GetProperties();
foreach (PropertyInfo item in attributes)
{
    Console.WriteLine($"全类名:{item.PropertyType.FullName} 属性名:{item.Name}");                
}

获取指定属性(属性一般使用public修饰,可直接获取)

Type type = typeof(MyClass);
PropertyInfo field =  type.GetProperty("Name");

利用反射实例化对象

Type type = typeof(MyClass);
ConstructorInfo constructorInfo = type.GetConstructor(new Type[] { typeof(string),typeof(int),typeof(bool)});
object obj = constructorInfo.Invoke(new object[] {"jack",18,true});

利用反射调用方法

Type type = typeof(MyClass);
// 获取构造器
ConstructorInfo constructorInfo = type.GetConstructor(new Type[] { typeof(string),typeof(int),typeof(bool)});
// 实例化类对象
object obj = constructorInfo.Invoke(new object[] {"jack",18,true});
// 获取方法
MethodInfo method = type.GetMethod("addAll", BindingFlags.NonPublic | BindingFlags.Instance, null, new[] { typeof(int[]) }, null);
//第一个参数是实例化对象,第二个参数是方法传参
int res = (int)method.Invoke(obj, new object[] { new int[] { 1, 2, 3, 4 } });
posted @   勤匠  阅读(1)  评论(0编辑  收藏  举报
编辑推荐:
· AI与.NET技术实操系列:基于图像分类模型对图像进行分类
· go语言实现终端里的倒计时
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
阅读排行:
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 25岁的心里话
· 按钮权限的设计及实现
点击右上角即可分享
微信分享提示