当前位置: 首页 > 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;通过提供自动配置、快速开发和零配置的…...

RestClient

什么是RestClient RestClient 是 Elasticsearch 官方提供的 Java 低级 REST 客户端&#xff0c;它允许HTTP与Elasticsearch 集群通信&#xff0c;而无需处理 JSON 序列化/反序列化等底层细节。它是 Elasticsearch Java API 客户端的基础。 RestClient 主要特点 轻量级&#xff…...

大数据学习栈记——Neo4j的安装与使用

本文介绍图数据库Neofj的安装与使用&#xff0c;操作系统&#xff1a;Ubuntu24.04&#xff0c;Neofj版本&#xff1a;2025.04.0。 Apt安装 Neofj可以进行官网安装&#xff1a;Neo4j Deployment Center - Graph Database & Analytics 我这里安装是添加软件源的方法 最新版…...

Prompt Tuning、P-Tuning、Prefix Tuning的区别

一、Prompt Tuning、P-Tuning、Prefix Tuning的区别 1. Prompt Tuning(提示调优) 核心思想:固定预训练模型参数,仅学习额外的连续提示向量(通常是嵌入层的一部分)。实现方式:在输入文本前添加可训练的连续向量(软提示),模型只更新这些提示参数。优势:参数量少(仅提…...

ssc377d修改flash分区大小

1、flash的分区默认分配16M、 / # df -h Filesystem Size Used Available Use% Mounted on /dev/root 1.9M 1.9M 0 100% / /dev/mtdblock4 3.0M...

解决Ubuntu22.04 VMware失败的问题 ubuntu入门之二十八

现象1 打开VMware失败 Ubuntu升级之后打开VMware上报需要安装vmmon和vmnet&#xff0c;点击确认后如下提示 最终上报fail 解决方法 内核升级导致&#xff0c;需要在新内核下重新下载编译安装 查看版本 $ vmware -v VMware Workstation 17.5.1 build-23298084$ lsb_release…...

ETLCloud可能遇到的问题有哪些?常见坑位解析

数据集成平台ETLCloud&#xff0c;主要用于支持数据的抽取&#xff08;Extract&#xff09;、转换&#xff08;Transform&#xff09;和加载&#xff08;Load&#xff09;过程。提供了一个简洁直观的界面&#xff0c;以便用户可以在不同的数据源之间轻松地进行数据迁移和转换。…...

【git】把本地更改提交远程新分支feature_g

创建并切换新分支 git checkout -b feature_g 添加并提交更改 git add . git commit -m “实现图片上传功能” 推送到远程 git push -u origin feature_g...

【数据分析】R版IntelliGenes用于生物标志物发现的可解释机器学习

禁止商业或二改转载&#xff0c;仅供自学使用&#xff0c;侵权必究&#xff0c;如需截取部分内容请后台联系作者! 文章目录 介绍流程步骤1. 输入数据2. 特征选择3. 模型训练4. I-Genes 评分计算5. 输出结果 IntelliGenesR 安装包1. 特征选择2. 模型训练和评估3. I-Genes 评分计…...

关键领域软件测试的突围之路:如何破解安全与效率的平衡难题

在数字化浪潮席卷全球的今天&#xff0c;软件系统已成为国家关键领域的核心战斗力。不同于普通商业软件&#xff0c;这些承载着国家安全使命的软件系统面临着前所未有的质量挑战——如何在确保绝对安全的前提下&#xff0c;实现高效测试与快速迭代&#xff1f;这一命题正考验着…...

基于Java+MySQL实现(GUI)客户管理系统

客户资料管理系统的设计与实现 第一章 需求分析 1.1 需求总体介绍 本项目为了方便维护客户信息为了方便维护客户信息&#xff0c;对客户进行统一管理&#xff0c;可以把所有客户信息录入系统&#xff0c;进行维护和统计功能。可通过文件的方式保存相关录入数据&#xff0c;对…...