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

Tencent Kona SM Suite:Java国密应用开发指南

Tencent Kona SM Suite&#xff1a;Java国密应用开发指南 【免费下载链接】TencentKonaSMSuite Tencent Kona SM Suite contains a set of Java security providers, which support algorithms SM2, SM3 and SM4, and protocols TLCP/GMSSL, TLS 1.3 (with RFC 8998) and TLS 1…...

为什么在银河麒麟上配置telnet?安全风险与替代方案探讨

银河麒麟系统中Telnet协议的深度安全剖析与现代替代方案 在国产操作系统银河麒麟上配置传统网络服务时&#xff0c;技术决策者常面临一个经典困境&#xff1a;是沿用熟悉的Telnet协议快速解决问题&#xff0c;还是投入资源迁移到更安全的现代方案&#xff1f;这个问题看似简单&…...

用AI辅助编程踩坑记:CH32V003驱动WS2812B,PWM+DMA配置避雷指南

CH32V003驱动WS2812B避坑实战&#xff1a;当AI生成的PWMDMA代码遇到现实 第一次尝试用AI辅助编写CH32V003驱动WS2812B的代码时&#xff0c;我天真地以为只要把芯片手册扔给AI就能得到完美运行的代码。直到LED灯带显示出诡异的彩虹乱码&#xff0c;我才意识到自己掉进了AI挖的多…...

在快马平台用Qt快速构建音乐播放器原型:十分钟搞定跨平台UI

最近在做一个音乐播放器的原型设计&#xff0c;尝试用Qt框架在InsCode(快马)平台上快速验证想法。整个过程比想象中顺利很多&#xff0c;特别适合需要快速验证UI方案的场景。这里记录下我的实践过程&#xff0c;分享给同样需要快速原型开发的朋友们。 为什么选择Qt做音乐播放器…...

【MicroPython编程-ESP32篇:设备驱动】-PCF8591数据采集驱动

PCF8591数据采集驱动 文章目录 PCF8591数据采集驱动 1、PCF8591介绍 2、软件准备 3、硬件准备与接线 4、程序实现 4.1 PCF8591驱动实现 4.2 主程序 1、PCF8591介绍 PCF8591 是一款单片集成、独立电源、低功耗、8 位 CMOS 数据采集设备。 PCF8591 具有四个模拟输入、一个模拟输…...

个人博客域名迁移说明 www.xiaoming.io

因为之前很多文章和插图都链接到了个人博客&#xff0c;一些读者评论和私信反馈链接有问题&#xff0c;图片不显示&#xff0c;这里特地说明如下&#xff1a;个人博客域名从原先的 www.hainter.com 改成了 www.xiaoming.io。例如文章中有链接 http://www.hainter.com/books 不能…...

5步掌控UEFI启动画面定制:HackBGRT终极实践指南

5步掌控UEFI启动画面定制&#xff1a;HackBGRT终极实践指南 【免费下载链接】HackBGRT Windows boot logo changer for UEFI systems 项目地址: https://gitcode.com/gh_mirrors/ha/HackBGRT 一、直面启动画面定制的三大痛点 在数字化时代&#xff0c;个性化已成为用户…...

OpenClaw性能优化:Phi-3-mini-128k-instruct长文本处理的缓存策略

OpenClaw性能优化&#xff1a;Phi-3-mini-128k-instruct长文本处理的缓存策略 1. 问题背景&#xff1a;长文本处理的性能瓶颈 最近在尝试用OpenClawPhi-3-mini处理公司100多页的技术文档时&#xff0c;遇到了严重的性能问题。每当需要对文档进行多轮分析或批量处理时&#xf…...

【RAG】基于 RAG 的知识库问答系统设计与实现

基于 RAG 的知识库问答系统设计与实现1. 系统介绍2. 技术与方法3. 核心功能代码片段3.1 知识库创建3.2 知识对话问答3.3 知识库清空4. 系统运行效果截图4.1 文件上传与知识库创建4.2 知识库问答4.3 文件删除与知识库清空总结项目代码地址&#xff1a;https://github.com/AI-Mee…...

大数据可视化

1. 传播分析评估维度&#xff1a;包含认知&#xff08;知晓、记忆&#xff09;、行动&#xff08;点击、搜索&#xff09;、情感&#xff08;喜好、美誉&#xff09;三个层面传统评估&#xff1a;主要关注广告点击率和观看次数等表面指标深度评估&#xff1a;需要分析广告观看后…...