在一线编码已有多年,积累了不少非常实用的技能,最近的更新会逐步的分享出来,希望能帮助到还有一丢丢喜欢.Net的朋友,当然这些都比较适合入门选手,虽然自己已是个精通抄代码的老猿,但技术造诣仍是渣渣。犹记得当年,自己凭借满腔热血,习得一身Java理论知识,一本《Java从入门到精通》常伴左右。初入大四后,已觉自己羽翼丰满,可以起飞,于是跃跃欲试,自信满满的外出找实习。我拿着自己精心制作的简历,上面一众“图书管理系统”、“学生成绩查询系统”、“酒店管理系统”、“出入库管理系统”等热血参与大制作。想着自己拥有如此丰厚的经历,offer定是信手拈来。第一家:五人大公司,深藏居民楼小角落大胡子:你知道PHP吗?我:……我想学java大胡子:PHP现在是最流行的语言,我们有专人带你,就看中你的好学。我:可是我想学java大胡子:给你一个月开1600,怎么样?我:好(真是毫无原则的狗蛋)……一礼拜后我离职了,他们哪里是在做开发,就是做拼接页面而已,我也只是整理资料,打扫卫生。第二家:10人超大公司,一间公寓小白脸:做过公司系统吗?我:(难道我做的都是玩的吗?)做的少。小白脸:做学生成绩查询系统时如何考虑并发?我:……小白脸:问了你几个问题,都是理论多,实操很少啊。我:……小白脸:给你个建议,别着急找工作,回去再好好学,基础不扎实么,要多做公司级系统。我:……第三家:15人巨头公司,居民楼老板:我们现在愿意招学生,愿意培养,java和.net都一样,条条大路通罗马,不用过于追求语言的差别,学好了都是大牛。我:是的是的(被一语道破心中疑虑,反正我小白一个,用什么技术栈都一样从零起步)老板:来我们公司,我带你……一如此门深似海,从此Java是路人。--------以上演绎都是本人真实经历改编,意在告诫各位语言无好坏,只有使用的人才有差别

我们来看下今天的主题:

听到反射,很多人应该和我一样有这么几个疑问:

1.DLL内容都了解的话,直接引用DLL不就好了吗,为什么还要反射?2.DLL里面的内容什么都不知道的话,就算反射的话,也不知道里面的方法是干什么的啊,和直接引用DLL没区别啊?

这几个问题先不着急回答,我们继续分析下。想要知道反射,就必须先了解一下计算机是如何运行我们写的代码的,如下图:

对于计算机来讲,它只认识01010101之类的二进制代码,人类写的高级语言(如C#、JAVA等)计算机是没法识别的,所以需要将高级语言转化为01让计算机可以识别的二进制编码,中间是有一个过程的。就拿C#来讲,VS编译器会将编写好的代码进行编译,编译后会生成exe/dll文件,.Net Core里面已经不生成exe了,都是dll。dll和exe还需要CLR/JIT的即时编译成字节码,才能最终被计算机执行。有伙伴就会问为什么要编译2次呢,先编译到dll,再编译到字节码01呢,为什么不能一次性编译成字节码呢?

因为我们写的是C#语言,但是真实运行的机器有很多种,可能是32位,也可能是64位,操作系统可能是windows、linux、unix等,不同的计算机不同的操作系统识别字节码的可能是不一样的,但是从高级语言编译成exe/dll这一步是一样的。所以只要在不同运行环境的计算机上安装对应的不同的CLR/JIT,就可以运行我们同一个exe/dll了。这里就大概讲下这样一个过程,后面会有章节详细讲解程序如何被计算机执行的。现在我们先关注编译生成的exe/dll,它包含2部分,分别是中间语言IL和源数据元数据metadata。IL里面包含我们写的大量的代码,比如说方法、实体类等。元数据metadata不是我们写的代码,它是编译器在编译的时候生成的描述,它可能是把命名空间、类名、属性名记录了一下,包括特性。

讲上面程序的编译过程跟反射有什么关系呢?我们反射就是读取metadata里面的数据的,然后去使用它。反射是.NET中的重要机制,通过反射可以得到*.exe或*.dll等程序集内部的接口、类、方法、字段、属性、特性等信息,还可以动态创建出类型实例并执行其中的方法。

一、反射的用途:

        类型                                          作用
Assembly

定义和加载程序集,加载程序集清单中列出的模块

,以及从此程序集中查找类型并创建该类型的实例

Module 了解包含模块的程序集以及模块中的类等,还可以获取在模块上定义的所有全局方法或其他特定的非全局方法。
ConstructorInfo 了解构造器的名称、参数、访问修饰符(如public或private)和实现详细信息(如abstract或virtual)等。使用Type的GetConstructors或GetConstructor方法来调用特定的构造函数。
MethodInfo 了解方法的名称、返回类型、参数、访问修饰符(如public或private)和实现详细信息(如abstract或virtual)等。使用Type的GetMethods或GetMethod方法来调用特定的方法。
FieldInfo 了解字段的名称、访问修饰符(如public或private)和实现详细信息(如static)等,并获取或设置字段值。
EventInfo 了解事件的名称、事件处理程序数据类型、自定义特性、声明类型和反射类型等,并添加或移除事件处理程序。
PropertyInfo 了解属性的名称、数据类型、声明类型、反射类型和只读或可写状态等,并获取或设置属性值。
ParameterInfo 了解参数的名称、数据类型、参数是输入参数还是输出参数等,以及参数在方法签名中的位置等。

二、反射实例

我们通过实际例子来看下反射的用途。

1.首先建立一个控制台程序,并添加一个类库,里面建立一个AnimalsInfo类

AnimalsInfo中定义如下属性和方法:

public  class AnimalsInfo    {        public string Type { get; set; }        public int Size { get; set; }        public void CommonMethod()        {            Console.WriteLine("我就是一个普通方法");        }        public void ParameterMethod(string type)        {            Console.WriteLine("我是带参数方法,我是" + type);        }        public void OverrideMethod(int size)        {            Console.WriteLine($"我是重载方法,我有{size}大");        }        public void OverrideMethod(string name)        {            Console.WriteLine("我是重载方法,我叫" + name);        }        public void GenericityMethod(T t)        {            Console.WriteLine("我是泛型方法方法,类型是" + typeof(T));        }        private void PrivateMethod()        {            Console.WriteLine("我是私有方法");        }        public static void StaticMethod()        {            Console.WriteLine("我是静态方法");        }    }

2.利用反射获取类库,属性

using System;//第一步引用命名空间using System.Reflection;namespace ReflectionTest{    class Program    {        static void Main(string[] args)        {            Console.WriteLine("以下是获取类库的");            //第二步,动态加载类库,一定写要获取类库的**绝对路径**            Assembly assembly = Assembly.LoadFile(@"C:\Users\XA-BAU-Lyvin\source\repos\ReflectionTest\ReflectionTest.Model\bin\Debug\netcoreapp3.1\ReflectionTest.Model.dll");            //第三步,动态获取类型,写类库的名称和类的名称            Type type = assembly.GetType("ReflectionTest.Model.AnimalsInfo");            Console.WriteLine(type.Name);            Console.WriteLine("以下是获取属性的");            //遍历类型的属性集合            foreach (var item in type.GetProperties())            {                Console.WriteLine("字段名:"+ item.Name + ",类型:" + item.PropertyType);            }        }    }}

 3.通过反射获取方法

  • 所有的方法都要指定要获取的方法名称

  • 创建方法,第一个参数,对象,第二个参数,是一个object对象数组,写对应的参数类型

  • 私有方法不一样,一定有看清楚,它指明是父类的私有方法

using System;//第一步引用命名空间using System.Reflection;namespace ReflectionTest{    class Program    {        static void Main(string[] args)        {            Console.WriteLine("以下是获取类库的");            //第二步,动态加载类库,一定写要获取类库的**绝对路径**            Assembly assembly = Assembly.LoadFile(@"C:\Users\XA-BAU-Lyvin\source\repos\ReflectionTest\ReflectionTest.Model\bin\Debug\netcoreapp3.1\ReflectionTest.Model.dll");            //第三步,动态获取类型,写类库的名称和类的名称            Type type = assembly.GetType("ReflectionTest.Model.AnimalsInfo");            Console.WriteLine(type.Name);            Console.WriteLine("以下是获取属性的");            //遍历类型的属性集合            foreach (var item in type.GetProperties())            {                Console.WriteLine("字段名:"+ item.Name + ",类型:" + item.PropertyType);            }            Console.WriteLine("==============普通方法==================");            //创建一个符合类型的对象            object oAnimal = Activator.CreateInstance(type);            //***所有的方法都要指定要获取的方法名称            MethodInfo commonMethod = type.GetMethod("CommonMethod");            //创建方法,第一个参数,对象,第二个参数,没有则为空            commonMethod.Invoke(oAnimal, null);            Console.WriteLine("==============带参数的方法==================");            MethodInfo parameterMethod = type.GetMethod("ParameterMethod");            //创建方法,第一个参数,对象,第二个参数,是一个object对象数组,写对应的参数类型            parameterMethod.Invoke(oAnimal, new object[] { "狗狗" });            Console.WriteLine("==============重载方法int参数==================");            MethodInfo overrideMethodInt = type.GetMethod("OverrideMethod", new Type[] { typeof(int) });            overrideMethodInt.Invoke(oAnimal, new object[] { 18 });            Console.WriteLine("==============重载方法string参数==================");            MethodInfo overrideMethodStrint = type.GetMethod("OverrideMethod", new Type[] { typeof(string) });            overrideMethodStrint.Invoke(oAnimal, new object[] { "喵喵" });            Console.WriteLine("==============泛型方法==================");            MethodInfo genericityMethod = type.GetMethod("GenericityMethod").MakeGenericMethod(new Type[] { typeof(int) });            genericityMethod.Invoke(oAnimal, new object[] { 45 });            Console.WriteLine("==============私有方法==================");            //指定要获取的方法名称,指明是父类的私有方法            MethodInfo privateMethod = type.GetMethod("PrivateMethod", BindingFlags.Instance | BindingFlags.NonPublic);            privateMethod.Invoke(oAnimal, null);            Console.WriteLine("==============静态方法=================");            MethodInfo staticMethod = type.GetMethod("StaticMethod");            staticMethod.Invoke(null, null);        }    }}
运行截图:

 三、总结

所有的反射应用方法都已经讲完了,看完以后感觉其实也没有什么神秘的,很简单对不对?当然,还有个问题要留给大家继续讨论了:如果通过反射还可以访问私有方法,那么设置私有方法的意义在哪呢?是否和私有类型的设计初衷违背了?


往期回顾:

  • “生如蝼蚁,当立鸿鹄之志”|2020年终总结

  • .net core 学习笔记

反射 数据类型_C#扫盲篇(一):反射机制情真意切的说相关推荐

  1. 反射 数据类型_c#反射,反射程序员的快乐

    1.什么是反射? 我们先来看一张图片吧. 根据树木的轮廓,我们在水中能得到,一棵一模一样的树木.好的,先带大家简单了解下,那么,再程序中是如何体现呢! 反射是.NET中的重要机制,通过反射,可以在运行 ...

  2. 反射 数据类型_Java基础:反射机制详解

    一.什么是反射: (1)Java反射机制的核心是在程序运行时动态加载类并获取类的详细信息,从而操作类或对象的属性和方法.本质是JVM得到class对象之后,再通过class对象进行反编译,从而获取t对 ...

  3. Java的反射机制,内含超简单实例代码(搞懂反射,这一篇就够了)

    一 首先来说说反射机制的概念: 程序在运行时, 对于类来说,可以知道该类的任意属性和方法: 对于对象来说,可以调用该对象的任意方法和属性: 就以上这种动态获取信息的机制就称为Java的反射机制 彻底了 ...

  4. 12000+字Java反射,一起全面了解Java反射机制,为学习框架铺路

    文章目录 Java反射机制 理解Class类 获取Class类实例 类的加载过程 类加载器ClassLoader 创建运行时类的对象 获取运行时类的结构 调用运行时类的指定结构 动态代理 Java反射 ...

  5. 反射实现方法调用(1):执行机制

    1. 反射简介    2. 使用反射 3. 反射调用方法的执行机制 1. 反射简介 程序集包含模块,而模块包含类型,类型又包含成员.反射则提供了封装程序集.模块和类型的对象.您可以使用反射动态地创建类 ...

  6. 【JAVA基础篇】反射

    一.反射的概念 是指在运行过程中,对于任意一个类,都能够知道这个类的所有属性和方法:对于任意一个对象,都能够调用这个对象的所有方法和属性.这种动态获取信息和动态调用方法的功能称为JAVA的反射机制. ...

  7. BGP 路由反射器详解,RR反射簇与RR的防环机制介绍与实验

    一.什么是RR RR(Route Reflector):路由反射器 由于水平分割的原因,为了保证AS内所有的BGP路由器都能学习到完整的BGP路由,就必须在AS内实现IBGP全互联. 然而实现IBGP ...

  8. iOS网络缓存扫盲篇--使用两行代码就能完成80%的缓存需求

    原文地址:https://github.com/ChenYilong/ParseSourceCodeStudy/blob/master/02_Parse的网络缓存与离线存储/iOS网络缓存扫盲篇.md ...

  9. 反射 字段_java核心基础之反射

    前言 大家好,我是 jack xu,今天跟大家介绍核心基础里面的反射,反射这个东西你说它重要也重要,不重要也不重要.重要是当你看一些框架的源码时候,里面会用到反射的代码,你不会是看不懂的.不重要是因为 ...

最新文章

  1. 在IOS中创建get,set方法
  2. DTU详解解读 概念到功能应用
  3. 解决VS2005下中文输入法全角半角混乱的补丁
  4. ext文件系统机制原理剖析
  5. mysql数据库自动重新连接_mysql数据库自动重新连接
  6. MySQL高级 - 日志 - 查询日志
  7. TOP级CG行业云渲染服务的演进之路
  8. 2.简易的登录页面(表单验证)(HTML+JavaScript+Jquery)
  9. mysql ( )连接_MySQL中concat函数(连接字符串)
  10. linux conda创建虚拟环境
  11. hibernate理解
  12. java 换行规范_Java代码规范
  13. Unity3D实战【一】Create Project 创建项目导入素材
  14. 打鼾,是一种全身性疾病
  15. matlab生成三维分形,MATLAB生成分形树.ppt
  16. 财报只是其中的一个因素
  17. You have not concluded your cherry-pick
  18. groovy入门-GString
  19. php 炸金花牌型 和 比牌 规则
  20. JAVA:实现binary exponentiation二进制幂运算算法(附完整源码)

热门文章

  1. A. Gamer Hemose
  2. 蔡高厅老师 - 高等数学阅读笔记 - 07 - 函数的微分 - 微分中值定理 罗尔、拉格朗日中值定理 (31、32、33、34、35)
  3. 互联网和大数据是什么意思_大数据和互联网的区别是什么意思
  4. hive mysql 字符集_Hive字符编码
  5. dll注入工具_bypassUAC amp;amp; DLL劫持
  6. eclipse java web乱码_JAVA and JAVA WEB with TOMCAT and ECLIPSE 学习过程中遇到的字符乱码问题及解决方法汇总(随时补充)...
  7. java lstm_人人都能看懂的LSTM介绍及反向传播算法推导(非常详细)
  8. dw怎么修改html框架的宽度,Dreamweaver (dw)cs6中div标签宽度和高度设置方法
  9. _Linux自编译云锁Web网站防火墙,看完小白也能保护网站安全
  10. 关于Chrome出现Provisional headers are shown无法正常访问的解决方案(其他firefox,360, IE访问正常) (转)...