【反射】C#:反射(Reflection)

本文深入探讨了C#中的反射机制,介绍了反射的基本概念、作用和使用方式,详细讲解了Type和Assembly类的属性与方法,并通过实例展示了如何在运行时创建类型实例、调用方法和访问属性。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

一、定义

反射(Reflection)指程序可以访问、检测和修改它本身状态或者行为的一种能力。
程序包含模块、类型、成员,反射提供的是封装程序集、模块、类型、成员的对象。

二、作用

可以动态创建类型的实例,将类型绑定到现有对象;或者从现有对象中获取类型。然后,可以调用类型的方法或者访问其字段和属性。

三、使用

1.用途

  • 它允许在运行时查看特性(attribute)信息
  • 它允许审查集合中的各种类型,以及实例化这些类型
  • 它允许延迟绑定的方法和属性(property)
  • 它允许在运行时创建新类型,然后使用这些类型执行一些任务

2.命名空间

using System.Reflection;
using System.Type;
using System.Reflection.Assembly;

常用的为Type和Assembly两个类。

3.属性与方法

Type类

属性说明
Name数据类型名
FullName获取该类型的完全限定名称,包括其命名空间,但不包括程序集。
Namespace定义数据类型的命名空间名
Attribute获取与 Type 关联的属性
CustomAttributes获取包含此成员自定义属性的集合。(继承自 MemberInfo)
方法说明
GetConstructors()返回ConstructorInfo类型数组,获取当前Type定义的所有公共构造函数
GetEvent(),GetEvents()返回EventInfo类型,获取该Type的事件信息
GetField(), GetFields()返回FieldInfo类型,获取该Type的字段(成员变量)的信息
GetInterface(), GetInterfaces()返回InterfaceInfo类型,获取该Type实现的接口的信息
GetMember(), GetMembers()返回MemberInfo类型,获取该Type的所有成员的信息
GetMethod(),GetMethods()返回MethodInfo类型,获取该Type的方法的信息
GetProperty(), GetProperties()返回PropertyInfo类型,获取该Type的属性的信息
GetEnumNames()返回当前枚举类型中各个成员的名称

更多请到Type官方文档…

Assembly类

Assembly类可以获取正在执行的程序集;可以动态加载程序集;以及在程序集中查找并创建类型实例。
使用:

//通过程序集名称返回Assembly对象
Assembly assembly = Assembly.Load("AssemblyName");
//通过dll文件名称返回Assembly对象
Assembly assembly = Assembly.LoadFrom("*.dll");
//通过Assembly对象获取具体类
Type t = assembly.GetType("ClassName");   //参数必须是全名

更多到 Assembly官方文档…

四、实例

using System;
using System.Reflection;

namespace ReflectionTest
{
    class Student
    {
        public Student() { }

        public Student(string name)
        {
            this.name = name;
        }

        public Student(string name, int age)
        {
            this.age = age;
            this.name = name;
        }

        private string name;

        private int age;

        public string Name { get { return name; } set { name = value; } }

        public int Age { get { return age; } set { age = value; } }

        public void Show()
        {
            Console.WriteLine("name:{0},age{1}", this.name, this.age);
        }
    }

    class Program
    {
        static void Main(string[] args)
        {

            Assembly assembly = Assembly.Load("ReflectionTest");        // 加载程序集

            Type t = assembly.GetType("ReflectionTest.Student");                       // 加载类

            // 1. 查看类中的构造方法与参数
            ConstructorInfo[] ciArr = t.GetConstructors();              // 获取类的所有构造函数
            foreach (var ci in ciArr)
            {
                ParameterInfo[] paras = ci.GetParameters();             // 循环每个构造函数获取并打印参数
                foreach (var para in paras)
                {
                    Console.WriteLine(para.ParameterType.ToString() + "\n" + para.Name);
                }
            }

            // 2. 查看类中的属性
            PropertyInfo[] pis = t.GetProperties();
            foreach (var pi in pis)
            {
                Console.WriteLine(pi.Name + "\n");
            }

            // 3. 用构造函数生成对象
            Type[] types = new Type[pis.Length];
            for (int i = 0; i < pis.Length; i++)
            {
                types[i] = pis[i].PropertyType;
            }
            ConstructorInfo ci0 = t.GetConstructor(types);
            object[] o = new object[] { "盖伦", 22 };
            object obj = ci0.Invoke(o);

            ((Student)obj).Show();

            // 4. 用Activator生成对象
            object[] o2 = new object[] { "亚索", 23 };
            object obj2 = Activator.CreateInstance(t, o2);
            ((Student)obj2).Show();

            // 5. 查看类中的方法(所有公共方法)
            foreach (var mi in t.GetMethods())
            {
                Console.WriteLine(mi.Name + "");
            }

            // 6. 取得类中的方法并执行
            object o3 = Activator.CreateInstance(t);             // 创建一个类的实例
            PropertyInfo nameF = t.GetProperty("Name");         // 获取Name属性
            nameF.SetValue(o3, "瑞文");
            PropertyInfo ageF = t.GetProperty("Age");           // 获取Age属性
            ageF.SetValue(o3, 18);

            MethodInfo methodInfo = t.GetMethod("Show");

            methodInfo.Invoke(o3, null);

            Console.ReadKey();

        }
    }
}

执行结果:
图1

五、总结

  • 优点

反射提高了程序的灵活性和拓展性;降低耦合性,提高自适应能力。它允许程序创建和控制任何类的对象,无需提供硬编码目标类。

  • 缺点

1、性能问题:使用反射基本上是一种解释操作,包括了一些动态的类型,用于字段和方法接入时要远慢于直接代码,因此反射操作的效率要比非反射操作慢很多。
2、使用反射会模糊程序内内部逻辑:程序员希望在源代码中看到程序的逻辑,反射等绕过了源代码的技术,因而会带来维护问题。反射代码比相应的直接代码更复杂

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值