C#学习,反射

目录

C#学习

.NET的体系结构

二次编译

反射

什么是反射?

什么是Type?

什么是程序集?

反射API:

一,程序集

1, Load

2,LoadFrom

3,LoadFile

二,类型实例

1,无参构造

2,有参构造

3,私有构造

4,泛型类

三,方法调用

1,普通方法

2,静态方法

3,私有方法

4,泛型方法

5,应用

四,属性与字段

1,属性读写

2,字段读写

3,应用

反射优缺点

优点

缺点

反射的价值是什么


C#学习

定义:面向对象,面向组件,类型安全,可以使用C#生成在.NET上运行的应用程序。

C#提供了语言构造来支持以上的定义,所以可以用来创建和使用软件组件。

.NET的体系结构

C#在.NET上运行,.NET叫做,公共语言进行时(CLR)的虚拟执行系统和一组类库.CLR 是 Microsoft 对公共语言基础结构 (CLI) 国际标准的实现。 CLI 是创建执行和开发环境的基础,语言和库可以在其中无缝地协同工作。

用 C# 编写的源代码被编译成符合 CLI 规范的中间语言 (IL)。 IL 代码和资源(如位图和字符串)存储在扩展名通常为 .dll 的程序集中。 程序集包含一个介绍程序集的类型、版本和区域性的清单(metadata)。

执行 C# 程序时,程序集将加载到 CLR。 CLR 会直接执行实时编译,将 IL 代码转换成本机指令。 CLR 可提供其他与自动垃圾回收、异常处理和资源管理相关的服务。

二次编译

目的:一次编译,多平台使用,加一层中间层,更加灵活

由于系统很多,Mac,Win,Linux,其中Win还有32和64位的,为了做到一次编译,多平台运行,就需要二次编译,C#源代码被编译成中间语言,存储在扩展名通常为 .dll 的程序集中, 程序集包含一个介绍程序集的类型、版本和区域性的清单(metadata)。

这样在不同的平台,同一份编译的中间语言,通过 CLR 转换为不同平台可执行机器指令,在不同平台执行。

反射

什么是反射?

程序是用来处理数据的,但是程序本身也是由数据组成的,有关程序及其类型的数据,元数据(Metadata),保存在程序集之中,程序在运行中,可以查看其他的程序集和自身的Metadata,一个运行的程序查看本身的元数据或其他程序集的元数据的行为称为反射。

什么是Type?

对于程序的类型,CLR都会创建一个包含这个类型的Type对象,程序中每遇到一个类型都会关联到独立的Type的对象,不管创建的类有多少实例,只有一个Type类的对象会关联到这些所有的实例。

什么是程序集?

程序集是一个可以寄宿于 CLR 中的、拥有版本号的、自解释、可配置的二进制文件,程序集的扩展名为 exe 或 dll。程序集是存放类型的集合,通过程序集可以获取程序集内所有的类型信息

反射API:

一,程序集

如果没有加载依赖,调用到使用依赖的对象时就会报错。

1, Load

XXX:dll 名称无后缀 从当前目录加载 dll。开发环境 Bin ,发布程序是入口程序集文件当前目录。

Assembly assembly = Assembly.Load("XXXX");
2,LoadFrom

XXX:已知程序集的文件名和路径,会自动加载程序集的依赖程序集。

Assembly assembly = Assembly.LoadFrom("XXXX");
3,LoadFile

XXX:完整的dll路径加载不会出错,不会加载目标程序集所引用和依赖的其他程序集,需要自己控制并显示加载所有依赖的程序集,如果没有依赖项,使用的时候会错。

Assembly assembly = Assembly.LoadFile("XXXX");

二,类型实例

1,无参构造

在获取Assembly后获取Type,根据Type创建实例,是Object类型的,为了编译器可以通过需要进行类型转换。

Type type = assembly.GetType("XXX.XXX");
object obj = (XXX)Activator.CreateInstance(type);
2,有参构造

在创建实例的时候,需要通过new object[]参数进行重载,此方法会根据 new object[] 里面的类型自动进行匹配构造函数

object obj = (XXX)Activator.CreateInstance(type, new object[] { "124", 123 });
3,私有构造

单例模式,在代码里面为了避免外面进行实例化,在实现时都是以 private 修饰符对构造函数进行修饰,使其无法在外部进行实例化进行调用,但反射可以破坏这个规则。重点在 CreateInstance 方法,第二个参数 true

Assembly assembly = Assembly.LoadFrom("XXXX");
Type type = assembly.GetType("XXX.XXX");
object obj = Activator.CreateInstance(type,true);
4,泛型类

~n个占位符就代表几个泛型,MakeGenericType 定义泛型类型,传入 Type 数组即可

Assembly assembly = Assembly.LoadFrom("XXXX");
Type type = assembly.GetType("XXX~n");
Type typeNew = type.MakeGenericType(new Type[] { typeof(int), typeof(XXX),typeof(string)  });
object obj = Activator.CreateInstance(typeNew, new object[] { "124", 123 });

三,方法调用

1,普通方法
Assembly assembly = Assembly.Load("XXX");// dll
Type type = assembly.GetType("XXX");// 类型名称
object instance = Activator.CreateInstance(type); // 根据 type 实例对象
MethodInfo method = type.GetMethod("XXX");// 方法名称
method.Invoke(instance,new object[] { "方法参数1", "方法参数2" });
2,静态方法

静态成员,Invoke 无需传入实例对象,因为静态成员在类里面,只有一份,确定了 Type 后就已经有了其静态成员。

Assembly assembly = Assembly.Load("XXX");// dll
Type type = assembly.GetType("XXX");// 类型名称
MethodInfo method = type.GetMethod("XXX");// 方法名称
method.Invoke(null,new object[] { "方法参数1", "方法参数2" });
3,私有方法

私有方法在面向对象编程语言是不可以被外部调用的,但反射可以破坏这个规则调用私有方法,重点在 GetMethod 方法第二个参数为 BindingFlags.Instance|BindingFlags.NonPublic。

Assembly assembly = Assembly.Load("XXX");// dll
Type type = assembly.GetType("XXX");// 类型名称
object instance = Activator.CreateInstance(type); // 根据 type 实例对象
MethodInfo method = type.GetMethod("XXX",BindingFlags.Instance|BindingFlags.NonPublic);// 方法名称
method.Invoke(instance, new object[] { "方法参数1", "方法参数2" });
4,泛型方法

无论是泛型类还是泛型方法,都需要通过 MakeGenericXXXX 方法指定泛型的类型,需要注意的是泛型类在加载类型时需要占位符,而泛型方法不需要。

Assembly assembly = Assembly.Load("XXX");// dll
Type type = assembly.GetType("XXX~2");// 类型名称,~2 占位符,代表几个泛型
Type typeNew = type.MakeGenericType(new Type[] { typeof(string), typeof(int) });
object instance = Activator.CreateInstance(typeNew); // 根据 type 实例对象
MethodInfo method = type.GetMethod("XXX");// 方法名称
MethodInfo methodNew = method.MakeGenericMethod(new Type[] { typeof(int) });
methodNew.Invoke(instance, new object[] { "方法参数1", "方法参数2" });
5,应用

MVC就是使用的反射机制,在程序启动时,会扫描 controller 类型的类,会将其 Type 缓存起来,当有请求过来时,就会到缓存中找到对于的 Type 反射进行实例化并调用其方法(也就是 action)。说到这 mvc 的 filter 也就是在 调用方法前后加点料(反射 invoke 方法前后)。

四,属性与字段

1,属性读写
Assembly assembly = Assembly.Load("XXX");// dll
Type type = assembly.GetType("XXX.XXX");// 类型名称
object instance = Activator.CreateInstance(type); //实例对象
foreach (var prop in type.GetProperties())
{if (prop.Name.Equals("Id")){prop.SetValue(instance, 1);Console.WriteLine(prop.GetValue(instance));}else if (prop.Name.Equals("Name")){prop.SetValue(instance, "张三");Console.WriteLine(prop.GetValue(instance));}
}
2,字段读写
Assembly assembly = Assembly.Load("XXX");// dll
Type type = assembly.GetType("XXX.XXX");// 类型名称
object instance = Activator.CreateInstance(type); //实例对象
foreach (var field in type.GetFields())
{if (field.Name.Equals("id")){field.SetValue(instance, 1);Console.WriteLine(field.GetValue(instance));}else if (field.Name.Equals("name")){field.SetValue(instance, "张三");Console.WriteLine(field.GetValue(instance));}
}
3,应用

有一个 entity 与 entityDto:

public class Product
{public int ID { get; set; }public String Name { get; set; }
}
public class ProductDto
{public int ID { get; set; }public String Name { get; set; }
}

然后对 entity 承载的数据进行了实例化,并且依次赋值个了 entityDto

Product product = new Product()
{ID = 1,Name = "张三"
};
​
ProductDto productDto = new ProductDto();
productDto.ID = product.ID;
productDto.Name = product.Name;

对于上面的情况,还算简单,但是如果字段过多,手动赋值要花费的时间就大大增加,于是我们可以采用反射机制来提高效率,自动赋值,实际应用时,我们可以使用T来进行封装:

Product product = new Product()
{ID = 1,Name = "张三"
};
Type productType = typeof(Product); // Product Type
Type productDtoType = typeof(ProductDto);// ProductDto Type
object productDto = Activator.CreateInstance(productDtoType); // ProductDto Instance
foreach (var prop in productDtoType.GetProperties())
{// 依次拿取 dto 属性名称,在 Product Type 查找,并且从 Product Instance 获取值object val = productType.GetProperty(prop.Name).GetValue(product);// ProductDto Instance Set Propertie Valprop.SetValue(productDto,val);
}

反射优缺点

优点

动态:反射就两个字动态,就像 MVC 就是将方法的调用动态化了。数据库或者封装的处理业务逻辑的算法等,可以使用配置文件进行动态切换使用。

缺点
  • coding 复杂:面向对象静态编码,一两行的代码反射得写个四五行。

  • 避开编译器检查:平时写代码,我们写错了,编译的时候会 error 提示我们,如果没有编译器写得代码不知道错多少。但在反射里面,编译器对类的操作不会进行检查,这也是没有办法检查,因为反射是动态的运行时的,不像普通编码是静态的。

反射的价值是什么

反射最直观的区别是,由已有的固定类型,转化为了字符串操作,且不需要在项目中进行引用(反射是动态的,依赖的是字符串)。因为依赖的是字符串,我们的程序才可配置化、才可易扩展,包括平时的框架开发都在大量使用反射(MVC、IOC、ORM等)。

学习参考自:菜鸟厚非

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/37932.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

SSM中接口+mapper文件(增删改查)

IActivateInfoDao接口 public interface IActivateInfoDao{//根据用户id和验证类型,判断认证是否已存在ActivateInfo selectByUserIdAndType(Param("userId") String userId, Param("type") String type);//插入int insert(ActivateInfo activ…

一文读懂c++语言

一文读懂C语言 C的发展C的设计目标C的特性C的挑战 C的发展 C是一种通用的、高级的编程语言,它是C语言的扩展。C由Bjarne Stroustrup于1983年首次引入,并在之后的几十年中不断发展壮大。C被广泛应用于各种领域,包括系统开发、游戏开发、嵌入式…

pytest数据驱动(最简单)

目录 第一种:通过yaml文件获取数据(一维列表) 第二种:通过yaml文件获取数据(二维列表) 第三种:通过yaml文件获取数据(pytest.fixture) 资料获取方法 第一种&#xff…

国际腾讯云账号云核算概述!!

云核算概述 维基百科界说:云核算是一种依据互联网的新型核算方法,经过互联网上异构、自治的服务为个人和企业供给按需即取的核算。 云核算描绘的一起特征:云是一种按需运用的服务,运用者只重视服务本身。 云核算作为IT服务形式&am…

四、Linux中cd、pwd以及相对/绝对路径和特殊路径符

1、cd命令: cd命令可以切换当前工作目录,基础语法是: cd [linux路径] (1)、打开Linux的命令提示行,当前工作目录是home,输入“cd /”,可以切换到根目录下,在根目录下输…

6_AccessKeyId和AccessKeySecret的环境变量配置

系列文章目录 第1章 Linux安装Docker 第2章 Docker安装jdk1.8和MySql 第3章 Docker安装redis 第4章 Jar包部署Docker 第5章 Docker-compose多服务统一编排管理 第6章 AccessKeyId和AccessKeySecret的环境变量配置 文章目录 系列文章目录前言一、WIN系统配置二、LINUX系统配置三…

【go语言学习笔记】05 Go 语言实战

文章目录 一、 RESTful API 服务1. RESTful API 定义1.1 HTTP Method1.2 RESTful API 规范 2. RESTful API 风格示例3. RESTful JSON API4. Gin 框架4.1 导入 Gin 框架4.2 使用 Gin 框架4.2.1 获取特定的用户(GET)4.2.2 新增一个用户(POST&am…

【前端 | CSS】align-items与align-content的区别

align-items 描述 CSS align-items 属性将所有直接子节点上的 align-self 值设置为一个组。align-self 属性设置项目在其包含块中在交叉轴方向上的对齐方式 align-items是针对每一个子项起作用,它的基本单位是每一个子项,在所有情况下都有效果&…

SpringBoot复习:(31)Controller中返回的对象是如何转换成json字符串给调用者的?

首先,SpringBoot自动装配了HttpMessageConvertersAutoConfiguration这个自动配置类 而这个自动配置类又通过Import注解导入了JacksonHttpMessageConvertersConfiguration类, 在这个类中配置了一个类型为MappingJackson2HttpMessageConverter类型的bean…

vant van-tabs van-pull-refresh van-list 标签栏+上拉加载+下拉刷新

<template><div class"huibj"><div class"listtab"><!--顶部导航--><div class"topdh"><topnav topname"余额明细"></topnav></div><!--Tab 标签--><van-tabs v-model"…

Python教程(9)——Python变量类型列表list的用法介绍

列表操作 创建列表访问列表更改列表元素增加列表元素修改列表元素删除列表元素 删除列表 在Python中&#xff0c;列表&#xff08;list&#xff09;是一种有序、可变的数据结构&#xff0c;用于存储多个元素。列表可以包含不同类型的元素&#xff0c;包括整数、浮点数、字符串等…

配置 yum/dnf 置您的系统以使用默认存储库

题目 给系统配置默认存储库&#xff0c;要求如下&#xff1a; YUM 的 两 个 存 储 库 的 地 址 分 别 是 &#xff1a; ftp://host.domain8.rhce.cc/dvd/BaseOS ftp://host.domain8.rhce.cc/dvd/AppStream vim /etc/yum.repos.d/redhat.repo [base] namebase baseurlftp:/…

C语言快速回顾(一)

前言 在Android音视频开发中&#xff0c;网上知识点过于零碎&#xff0c;自学起来难度非常大&#xff0c;不过音视频大牛Jhuster提出了《Android 音视频从入门到提高 - 任务列表》&#xff0c;结合我自己的工作学习经历&#xff0c;我准备写一个音视频系列blog。C/C是音视频必…

Rabbitmq延迟消息

目录 一、延迟消息1.基于死信实现延迟消息1.1 消息的TTL&#xff08;Time To Live&#xff09;1.2 死信交换机 Dead Letter Exchanges1.3 代码实现 2.基于延迟插件实现延迟消息2.1 插件安装2.2 代码实现 3.基于延迟插件封装消息 一、延迟消息 延迟消息有两种实现方案&#xff…

2016年,进了百度

昨在深圳出差&#xff0c;与微信里的朋友吃了个便饭&#xff0c;他是今年四月份加的我微信&#xff08;gaoyang677&#xff09;&#xff0c;他的经历很有意思&#xff0c;经他许可&#xff0c;分享给大家。 2012年时候&#xff0c;他大学毕业来到深圳&#xff0c;进了厂子&…

vue3 setup+Taro3 调用原生小程序自定义年月日时分多列选择器,NutUI改造

vue3 setupTaro3 调用原生小程序自定义年月日时分多列选择器&#xff0c;NutUI改造 NutUI 有日期时间选择器&#xff0c;但是滑动效果太差&#xff0c;卡顿明显。换成 原生小程序 很顺畅 上代码&#xff1a; <template><view><pickermode"multiSelector&…

2023牛客暑期多校训练营9-J Puzzle: Star Battle

2023牛客暑期多校训练营9-J Puzzle: Star Battle https://ac.nowcoder.com/acm/contest/57363/J 文章目录 2023牛客暑期多校训练营9-J Puzzle: Star Battle题意解题思路代码 题意 解题思路 出题人都说是诈骗题&#xff08;&#xff0c;可以发现满足每行每列恰好有 n n n个星…

python数据结构和算法

python数据结构和算法 参考 python图解算法 选择/快速排序 哈希表 广度优先搜索算法 迪杰斯特拉算法 贪婪算法 动态规划 K-邻近算法 计算机科学是解决问题的研究。计算机科学使用抽象作为表示过程和数据的工具。抽象的数据类型允许程序员通过隐藏数据的细节来管理问题领域的…

【解决】Kafka Exception thrown when sending a message with key=‘null‘ 异常

问题原因&#xff1a; 如下图&#xff0c;kafka 中配置的是监听域名的方式&#xff0c;但程序里使用的是 ip:port 的连接方式。 解决办法&#xff1a; kafka 中配置的是域名的方式&#xff0c;程序里也相应配置成 域名:port 的方式&#xff08;注意&#xff1a;本地h…

机器学习笔记之优化算法(十三)关于二次上界引理

机器学习笔记之优化算法——关于二次上界引理 引言回顾&#xff1a;利普希兹连续梯度下降法介绍 二次上界引理&#xff1a;介绍与作用二次上界与最优步长之间的关系二次上界引理证明过程 引言 本节将介绍二次上界的具体作用以及它的证明过程。 回顾&#xff1a; 利普希兹连续…