在一线编码已有多年,积累了不少非常实用的技能,最近的更新会逐步的分享出来,希望能帮助到还有一丢丢喜欢.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 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对象数组,写对应的参数类型
  • 私有方法不一样,一定有看清楚,它指明是父类的私有方法
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);
}

 三、总结

所有的反射应用方法都已经讲完了,看完以后感觉其实也没有什么神秘的,很简单对不对?

当然,还有个问题要留给大家继续讨论了:如果通过反射还可以访问私有方法,那么设置私有方法的意义在哪呢?是否和私有类型的设计初衷违背了?

首发自:【程序员不帅哥 】公众号

原文链接:https://mp.weixin.qq.com/s/LCPLjBmmbJwXBDWdi3SU1g

扫码关注,更多精彩内容及时获取,一起提高,一起加油

C#扫盲篇(一):反射机制--情真意切的说的更多相关文章

  1. 文末送书四本 | 这篇Java反射机制太经典!不看后悔!

    先看再点赞,给自己一点思考的时间,如果对自己有帮助,微信搜索[程序职场]关注这个执着的职场程序员. 价值:Java技能,面试经验指导,简历优化,职场规划指导,技能提升方法,讲不完的职场故事,个人成长经 ...

  2. javaSE高级篇4 — 反射机制( 含类加载器 ) — 更新完毕

    反射机制 1.反射机制是什么?----英文单词是:reflect.在java.lang包下---这才是java最牛逼的技术 首先提前知道一句话----在java中,有了对象,于是有了类,那么有了类之后 ...

  3. C#扫盲篇(三):Action和Func委托--实话实说

    一.基础定义 老王想找老张的老婆出去耍,但是一看,老张还在厨房煮饭.于是老王就对老张隔壁的淑芬说:"等下老张吃完饭出去喝茶,你就把前门晒的苞谷收了,老张从左门出,你就收右边的苞谷,我就知道从 ...

  4. C#扫盲篇(四):.NET Core 的异步编程-只讲干货(async,await,Task)

    关于async,await,task的用法和解释这里就不要说明了,网上一查一大堆.至于为啥还要写这篇文章,主要是其他文章水分太多,不适合新手学习和理解.以下内容纯属个人理解,如果有误,请高手指正.本文 ...

  5. Java 反射机制[Method反射]

    Java 反射机制[Method反射] 接着上一篇Java 反射机制[Field反射],通过调用Person类的setName方法将obj的name字段的Value设置为"callPerso ...

  6. 【Java入门提高篇】Day13 Java中的反射机制

    前一段时间一直忙,所以没什么时间写博客,拖了这么久,也该更新更新了.最近看到各种知识付费的推出,感觉是好事,也是坏事,好事是对知识沉淀的认可与推动,坏事是感觉很多人忙于把自己的知识变现,相对的在沉淀上 ...

  7. Httpd服务入门知识-http协议版本,工作机制及http服务器应用扫盲篇

    Httpd服务入门知识-http协议版本,工作机制及http服务器应用扫盲篇 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 一.Internet与中国 Internet最早来源于美 ...

  8. Java高级特性——反射机制(第二篇)

    在Java高级特性——反射机制(第一篇)中,写了很多反射的实例,可能对于Class的了解还是有点迷糊,那么我们试着从内存角度去分析一下. Java内存 从上图可以看出,Java将内存分为堆.栈.方法区 ...

  9. 11.Java反射机制 哦对了,前面的序号来自随笔关于编程之路的思索第一篇

    基本概念 在Java运行时环境中,对于任意一个类,能否知道这个类有哪些属性和方法?对于任意一个对象,能否调用它的任意一个方法? 答案是肯定的. 这种动态获取类的信息以及动态调用对象的方法的功能来自于J ...

随机推荐

  1. 【科技】单 $\log$ 合并两棵有交集 FHQ-Treap 的方法

    维护可分裂 & 合并的可重集 考虑这样一个问题: 维护 \(n\) 个 可重集 \(S_1, S_2, \cdots, S_n\),元素值域为 \([1, U]\),初始集合为空.支持一下操作 ...

  2. AcWing 404. 婚礼

    大型补档计划 题目链接 根据题意,显然只有新郎这边可能存在矛盾,考虑这边怎么放即可,新娘那边的放法与这边正好相反且一一对应. 显然对于两个约束条件是一对矛盾,开始我以为可以用并查集,后来发现输出方案的 ...

  3. basic english

    color/visual see look color dark light beautiful shade black blue brown clear gray green orange red ...

  4. 一起看下MySQL的崩溃恢复到底是怎么回事

    目录 回顾 思考一个问题 checkponit机制 Checkpoint的种类及触发条件 LSN 推荐阅读 本文稍微有点晦涩.但是看过之后你就能Get到MySQL的崩溃恢复到底是怎么做的! 文章公号 ...

  5. 一、Nginx笔记--linux下载安装部署Nginx

    Nginx 到底是什么? Nginx  是⼀个⾼性能的HTTP和反向代理web服务器,核⼼特点是占有内存少,并发能⼒强 Nginx ⼜能做什么事情(应⽤场景) Http服务器(Web服务器) 性能⾮常 ...

  6. 移动 WEB 开发的布局方式 ---- 响应式布局

    一.响应式简介 一个页面布局兼容了 PC端 ,iPad端 和 移动端 所谓的响应式就是页面中的布局会随着屏幕的大小变化发生了响应而做出不同的页面布局模型 特点: 响应式布局是不需要单独写移动端页面的 ...

  7. Linux下yum下载依赖包

    先安装依赖包yum-plugin-downloadonly [root@node1 ~]# yum install yum-plugin-downloadonly 方法一: [root@node1 ~ ...

  8. AWT08-绘图

    1.组件绘图原理 Java GUI能展示出不同对话框.窗口等等组件外观的本质其实就是绘图. 在AWT中,真正提供绘图功能的是Graphics对象,在Component中提供了三个方法来完成组件图形的绘 ...

  9. 带宽、延时、吞吐率、PPS 这些都是啥?

    Linux 网络协议栈是根据 TCP/IP 模型来实现的,TCP/IP 模型由应用层.传输层.网络层和网络接口层,共四层组成,每一层都有各自的职责. 应用程序要发送数据包时,通常是通过 socket ...

  10. Protobuf简单类型直接反序列化方法

    我有一个想法,有一个能够进行跨平台的高性能数据协议规范,能够让数据在两个不同的程序之间进行读取,最好能够支持直接将object序列化,那就完美了. 目标 支持任意Object序列化 支持从类似Syst ...