当前位置: 首页 > news >正文

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等)。

学习参考自:菜鸟厚非

相关文章:

C#学习,反射

目录 C#学习 .NET的体系结构 二次编译 反射 什么是反射? 什么是Type? 什么是程序集? 反射API: 一,程序集 1, Load 2,LoadFrom 3,LoadFile 二,类型实例 1&a…...

代理模式概述

1.代理模式概述 学习内容 1)概述 为什么要有 “代理” ? 生活中就有很多例子,比如委托业务,黄牛(票贩子)等等代理就是被代理者没有能力或者不愿意去完成某件事情,需要找个人代替自己去完成这…...

最新AI系统ChatGPT网站程序源码+搭建教程/公众号/H5端/安装配置教程/完整知识库

1、前言 SparkAi系统是基于国外很火的ChatGPT进行开发的Ai智能问答系统。本期针对源码系统整体测试下来非常完美,可以说SparkAi是目前国内一款的ChatGPT对接OpenAI软件系统。 那么如何搭建部署AI创作ChatGPT?小编这里写一个详细图文教程吧!…...

前端Flex布局

day06-Flex布局 目标:熟练使用 Flex 完成结构化布局 01-标准流 标准流也叫文档流,指的是标签在页面中默认的排布规则,例如:块元素独占一行,行内元素可以一行显示多个。 [外链图片转存失败,源站可能有防盗链机制,建议…...

文盘Rust -- Mutex解决并发写文件乱序问题 | 京东云技术团队

在实际开发过程中,我们可能会遇到并发写文件的场景,如果处理不当很可能出现文件内容乱序问题。下面我们通过一个示例程序描述这一过程并给出解决该问题的方法。 use std::{fs::{self, File, OpenOptions},io::{Write},sync::Arc,time::{SystemTime, UNI…...

数据结构算法--2 冒泡排序,选择排序,插入排序

基础排序算法 冒泡排序 思想就是将相邻元素两两比较,当一个元素大于右侧相邻元素时,交换他们的位置,小于右侧元素时,位置不变,最终序列中的最大元素,像气泡一样,到了最右侧。 这时冒泡排序第一…...

秋招面经——快手

Mysql mysql事务 共享锁与排他锁 共享锁:允许一个事务去读一行,阻止其他事务获得相同数据集的排他锁。(读都允许读,但我在读不允许你去改) 排他锁:允许一个事务去读一行,阻止其他事务获得相同…...

【STM32RT-Thread零基础入门】 2. 新建RT-Thread项目

硬件:STM32F103ZET6、ST-LINK、usb转串口工具 文章目录 前言一、新建RT-Thread项目二、项目结构三、构建项目四、下载程序(调试器下载)五、终端交互总结 前言 RT-Thread的全称是Real Time Thread,顾名思义,它是一个嵌…...

别人直播的时候怎么录屏?分享一些录屏方法

​随着互联网的快速发展,直播已经成为人们日常生活中不可或缺的一部分。但是,有时候我们可能会错过某些重要的直播内容,这时候就需要录屏来保存和观看。那么,如何录屏别人的直播呢?本文将分享一些录屏方法和技巧&#…...

React Native 在高IOS版本下无法显示图片的问题处理

图片在低ios版本下可以看到图片,在高版本ios下显示不了图片 直接上解决方法 找文件 /node_modules/react-native/Libraries/Image/RCTUIImageViewAnimated.m 修改源码 原代码 if (_currentFrame) {layer.contentsScale self.animatedImageScale;layer.contents…...

SSH远程连接MacOS catalina并进行终端颜色配置

一、开关SSH服务 在虚拟机上安装了MacOS catalina,想要使用SSH远程进行连接,但是使用“系统偏好设置”/“共享”/“远程登录”开关进行打开,却一直是正在启动“远程登录”: 难道是catalina有BUG?不过还是有方法的&…...

用JSON.toJSONString转JSON时,属性的值为null时,输出的JSON里没有该属性

1、问题 用JSON.toJSONString转JSON时,当属性值为null的话,转出来的JSON里没有了值为null的属性,属性丢失了 2、原因 用fastjson将java对象转json字符串时会默认去除空字段 2、解决办法 在JSON.toJSONString方法加上SerializerFeature这一…...

Java版企业电子招标采购系统源码—企业战略布局下的采购寻源tbms

​ 项目说明 随着公司的快速发展,企业人员和经营规模不断壮大,公司对内部招采管理的提升提出了更高的要求。在企业里建立一个公平、公开、公正的采购环境,最大限度控制采购成本至关重要。符合国家电子招投标法律法规及相关规范,以…...

轻拍牛头(约数)

题意&#xff1a;求ai在n个数中&#xff0c;ai可以整除的数有多少个&#xff0c;不包括ai自己。 分析&#xff1a;暴力写需要n^2的时间复杂度&#xff0c;此时想一下预处理每个数的倍数&#xff0c;约数和倍数是有关系的&#xff0c;把每个数的倍数都加上1. #include<bits…...

Vc - Qt - 绘制窗口背景色

要在Qt中绘制一个背景颜色&#xff0c;你可以使用Qt的绘图功能来完成。下面是一种简单的方法&#xff1a; 步骤1&#xff1a;在你想要绘制背景颜色的QWidget&#xff08;例如QMainWindow或QDialog&#xff09;的派生类中&#xff0c;重写 它的paintEvent函数。步骤2&#xff1a…...

js和cocos creator学习笔记

1.Javascript有哪些数据类型?举例两个最常见的内置对象数据类型? 常用的数据类型:Number,String,Boolean,Null,Undefined,Object 常见内置对象:Array,Function2.下面代码输出内容是什么? let a []; a[10] 10; console.log(a.length); console.log(a[0]); a[200] undefi…...

Ceph分布式存储系统

Ceph 是一个开源的分布式存储系统&#xff0c;旨在提供高性能、高可靠性和可扩展性的存储解决方案。它被设计用于管理大规模的数据&#xff0c;可以轻松地扩展到数千台服务器和多个存储节点&#xff0c;适用于私有云、公有云、虚拟化环境等多种场景。 Ceph 的主要特点和组件包…...

阿里云SMS,APi接口返回错误码

API错误码 更新时间&#xff1a;2023-06-29 16:33提交缺陷 产品详情 相关技术圈 我的收藏 调用API接口失败时&#xff0c;会返回错误码。本文档为您提供API接口错误码列表&#xff0c;请根据错误码和对应错误信息排查问题。 错误码&#xff08;Code&#xff09; 错误信息…...

Floyd算法

正如我们所知道的&#xff0c;Floyd算法用于求最短路径。Floyd算法可以说是Warshall算法的扩展&#xff0c;三个for循环就可以解决问题&#xff0c;所以它的时间复杂度为O(n^3)。 Floyd算法的基本思想如下&#xff1a;从任意节点A到任意节点B的最短路径不外乎2种可能&#xff…...

SpringBoot究竟应该如何学习?

如果你有Spring的基础&#xff0c;学习Spring Boot就很简单了。 首先要知道Spring Boot是建立在Spring框架之上的&#xff0c;它旨在简化和加速Java应用程序的开发过程。 Spring Boot的目标是简化Spring应用程序的配置和开发&#xff0c;通过提供自动配置、快速开发和零配置的…...

React Native 开发环境搭建(全平台详解)

React Native 开发环境搭建&#xff08;全平台详解&#xff09; 在开始使用 React Native 开发移动应用之前&#xff0c;正确设置开发环境是至关重要的一步。本文将为你提供一份全面的指南&#xff0c;涵盖 macOS 和 Windows 平台的配置步骤&#xff0c;如何在 Android 和 iOS…...

Admin.Net中的消息通信SignalR解释

定义集线器接口 IOnlineUserHub public interface IOnlineUserHub {/// 在线用户列表Task OnlineUserList(OnlineUserList context);/// 强制下线Task ForceOffline(object context);/// 发布站内消息Task PublicNotice(SysNotice context);/// 接收消息Task ReceiveMessage(…...

Redis相关知识总结(缓存雪崩,缓存穿透,缓存击穿,Redis实现分布式锁,如何保持数据库和缓存一致)

文章目录 1.什么是Redis&#xff1f;2.为什么要使用redis作为mysql的缓存&#xff1f;3.什么是缓存雪崩、缓存穿透、缓存击穿&#xff1f;3.1缓存雪崩3.1.1 大量缓存同时过期3.1.2 Redis宕机 3.2 缓存击穿3.3 缓存穿透3.4 总结 4. 数据库和缓存如何保持一致性5. Redis实现分布式…...

React Native在HarmonyOS 5.0阅读类应用开发中的实践

一、技术选型背景 随着HarmonyOS 5.0对Web兼容层的增强&#xff0c;React Native作为跨平台框架可通过重新编译ArkTS组件实现85%以上的代码复用率。阅读类应用具有UI复杂度低、数据流清晰的特点。 二、核心实现方案 1. 环境配置 &#xff08;1&#xff09;使用React Native…...

2.Vue编写一个app

1.src中重要的组成 1.1main.ts // 引入createApp用于创建应用 import { createApp } from "vue"; // 引用App根组件 import App from ./App.vue;createApp(App).mount(#app)1.2 App.vue 其中要写三种标签 <template> <!--html--> </template>…...

Python实现prophet 理论及参数优化

文章目录 Prophet理论及模型参数介绍Python代码完整实现prophet 添加外部数据进行模型优化 之前初步学习prophet的时候&#xff0c;写过一篇简单实现&#xff0c;后期随着对该模型的深入研究&#xff0c;本次记录涉及到prophet 的公式以及参数调优&#xff0c;从公式可以更直观…...

屋顶变身“发电站” ,中天合创屋面分布式光伏发电项目顺利并网!

5月28日&#xff0c;中天合创屋面分布式光伏发电项目顺利并网发电&#xff0c;该项目位于内蒙古自治区鄂尔多斯市乌审旗&#xff0c;项目利用中天合创聚乙烯、聚丙烯仓库屋面作为场地建设光伏电站&#xff0c;总装机容量为9.96MWp。 项目投运后&#xff0c;每年可节约标煤3670…...

使用van-uploader 的UI组件,结合vue2如何实现图片上传组件的封装

以下是基于 vant-ui&#xff08;适配 Vue2 版本 &#xff09;实现截图中照片上传预览、删除功能&#xff0c;并封装成可复用组件的完整代码&#xff0c;包含样式和逻辑实现&#xff0c;可直接在 Vue2 项目中使用&#xff1a; 1. 封装的图片上传组件 ImageUploader.vue <te…...

EtherNet/IP转DeviceNet协议网关详解

一&#xff0c;设备主要功能 疆鸿智能JH-DVN-EIP本产品是自主研发的一款EtherNet/IP从站功能的通讯网关。该产品主要功能是连接DeviceNet总线和EtherNet/IP网络&#xff0c;本网关连接到EtherNet/IP总线中做为从站使用&#xff0c;连接到DeviceNet总线中做为从站使用。 在自动…...

数据库分批入库

今天在工作中&#xff0c;遇到一个问题&#xff0c;就是分批查询的时候&#xff0c;由于批次过大导致出现了一些问题&#xff0c;一下是问题描述和解决方案&#xff1a; 示例&#xff1a; // 假设已有数据列表 dataList 和 PreparedStatement pstmt int batchSize 1000; // …...