C#中的反射关键类-Type

在C#中,存在程序集的概念,程序集就是我们所写的一个代码集合,经编译器编译后得到的供进一步编译执行的产物,某个代码库(.dll)文件或是某个可执行文件(.exe)都是程序集。对于程序的类,类内函数与变量等就是程序的元数据,元数据就是描述数据的数据,它被保存在程序集中。一个运行中的程序可以查看其他程序集或自身程序集的元数据,这个行为就叫做反射,通过反射,不仅可以得到程序集中的的信息,也可以对它们进行实例化,执行与操作。

C#中,Type类就是反射功能最基础的类,也称为类的信息类。通过它,我们可以访问元数据,获取有关类型声明的信息,也可以获取有关类型的成员

cs 复制代码
using System;
using System.Collections;
using System.Collections.Generic;
using System.Reflection;

namespace lesson20
{
    class Test 
    {
        private int i = 1;
        public int j = 0;
        public string str = "123";

        public Test() { }

        public Test(int i) 
        {
            this.i = i;
        }

        public Test(int i, string str) : this(i) 
        {
            this.str = str;
        }
        

        public void Speak() 
        {
            Console.WriteLine(i);
        }

    }
    class Program
    {
        static void Main(string[] args)
        {
            #region Type类(类的信息类)
            //获取Type
            //1.利用GetType()获取元数据的类型信息
            int a = 42;
            Type type = a.GetType(); 
            Console.WriteLine(type);
            //2.利用typeof关键字获取获取元数据的类型信息
            Type type2 = typeof(int);
            Console.WriteLine(type2);
            //3.利用类名获取类型信息
            Type type3 = Type.GetType("System.Int32");
            Console.WriteLine(type3);
            //不同Type变量得到的同种Type都指向同样的堆内存,一种类型仅有唯一的Type
            Console.WriteLine("****************************************************");
            //得到某个类的程序集信息
            Console.WriteLine(type.Assembly);
            Console.WriteLine("****************************************************");
            //获取类中的所有公共成员的类型信息
            Type t = typeof(Test);
            MemberInfo[] infos = t.GetMembers();
            for (int i = 0; i < infos.Length; i++) { Console.WriteLine(infos[i]); }
            Console.WriteLine("****************************************************");
            

            //获取类的公共构造函数并调用
            //1.获取所有构造函数信息
            ConstructorInfo[] ctors = t.GetConstructors();
            for (int i = 0; i < ctors.Length; i++) { Console.WriteLine(ctors[i]); }
            Console.WriteLine("****************************************************");
            //2.获取其中一个构造函数并执行
            /*
             构造函数的获取需要传入一个Type数组,用于存储该构造函数的参数类型
             构造函数的执行,需要传入一个object数组,用于按顺序传入参数
             */
            //获取无参构造
            ConstructorInfo info = t.GetConstructor(new Type[0]);
            //执行无参构造(对于无参构造函数的Invoke时直接传null)
            Test obj = info.Invoke(null) as Test;
            Console.WriteLine(obj.j);
            //获取有参构造
            ConstructorInfo info2 = t.GetConstructor (new Type[] { typeof(int)});
            obj = info2.Invoke(new object[] { 2 })as Test;
            Console.WriteLine(obj.str);

            ConstructorInfo info3 = t.GetConstructor(new Type[] {typeof(int),typeof(string)});
            obj = info3.Invoke(new object[] { 4,"yyyy"}) as Test;
            Console.WriteLine(obj.str);


            //获取类的公共成员变量
            //1.得到所有成员变量的信息
            Console.WriteLine("****************************************************");
            FieldInfo[] fieldInfos = t.GetFields();
            for (int i = 0; i < fieldInfos.Length; i++) { Console.WriteLine(fieldInfos[i]); }
            Console.WriteLine("****************************************************");
            //2.得到指定名称的公共变量的信息
            FieldInfo infoJ = t.GetField("j");
            Console.WriteLine(infoJ);
            //3.利用反射获取和设置对象的值
            Test test = new Test();
            test.j = 99;
            test.str = "2222";
            //通过反射获取对应变量的值
            Console.WriteLine(infoJ.GetValue(test));
            //通过反射设定对应变量的值
            infoJ.SetValue(test, 100);
            Console.WriteLine(infoJ.GetValue(test));

            //获取类的公共成员变量方法
            Console.WriteLine("****************************************************");
            Type strType = typeof(string);
            //1.获取所有公共成员方法
            MethodInfo[] methods = strType.GetMethods();
            for (int i = 0; i < methods.Length; i++) 
            {
                Console.WriteLine(methods[i]);
            }
            //2.获取某个公共成员方法
            //若存在成员方法的有参重载,利用Type数组表示参数类型
            MethodInfo subStr = strType.GetMethod("Substring",
                new Type[] { typeof(int),typeof(int) });
            //3.调用某个成员方法
            string str = "Hello,World!";
            Console.WriteLine("****************************************************");
            //第一个参数传入要调用该方法的对象,然后传入object数组来顺序传入参数
            //对于静态成员方法,第一个参数直接传入null
            object result =  subStr.Invoke(str, new object[] { 7, 5 });
            Console.WriteLine(result);
            #endregion
        }
    }
}
相关推荐
大黄说说1 小时前
Java 与 Kotlin 混合开发避坑指南:老项目平滑迁移 Kotlin 实操手册
java·开发语言·kotlin
breeze jiang1 小时前
JavaScript 单例模式:用静态属性保证 Popup 只创建一次
开发语言·javascript·单例模式
snow@li2 小时前
SpringBoot:AOP日志切面全景梳理/原理+流程+实战+避坑
java·开发语言·spring boot
Nil2082 小时前
C++ emplace_back 与 push_back 详解
开发语言·c++
clear sky .2 小时前
[freertos源码阅读]task.c任务篇
c语言·开发语言
XR1234567883 小时前
工业园区整体组网,方案对比怎么选?
开发语言·php
东东最爱敲键盘3 小时前
day9.C++多态之虚函数
开发语言·c++
码云数智-园园3 小时前
类似小鹅通的知识付费小程序平台有哪些
开发语言
淡海水3 小时前
15-07-YooAsset面试篇-Unity性能优化与内存管理
java·unity·面试·性能优化·c#·游戏引擎