C#反射详解

news2024/11/16 9:30:01

一、反射是什么

1、C#编译运行过程

高级语言->编译->dll/exe文件->CLR/JIT->机器码
在这里插入图片描述

2、原理解析

metadata:元数据数据清单,记录了dll中包含了哪些东西,是一个描述。
IL:中间语言,编译把高级语言编译后得到的C#中最真实的语言状态,面向对象语言。

反射:来自于System.Reflection,是一个帮助类库,可以读取dll/exe中metadata,使用metadata创建对象。

Emit:一种反射技术,可以动态创建dll/exe。

反编译工具:ILSpy可以反编译dll/exe,查看对应的C#/IL代码。

二、反射创建对象

1、动态读取dll

  • LoadFrom:dll全名称,需要后缀
  • LoadFile:全路径,需要dll后缀
  • Load:dll名称不需要后缀
//1、动态读取dll的三种方式
//(1)LoadFrom:dll全名称,需要后缀                        
Assembly assembly = Assembly.LoadFrom("Business.DB.SqlServer.dll");
//(2)LoadFile:全路径,需要dll后缀
//Assembly assembly1 = Assembly.LoadFile(@"dll文件全路径");
//(3)Load:dll名称 不需要后缀
//Assembly assembly2 = Assembly.Load("Business.DB.SqlServer");

获取类型

//2、获取某一个具体的类型,参数需要是类的全名称
Type type1 = assembly.GetType("Business.DB.SqlServer.SqlServerHelper");

3、创建对象

  • 直接传类型
  • 重载方法,传dll的全名称
  • 返回值是object类型,不能直接调用方法
//3、创建对象
//(1)直接传类型
object? oInstance = Activator.CreateInstance(type1);
//(2)重载方法,传dll的全名称
//object? oInstanc1= Activator.CreateInstance("Business.DB.SqlServer.dll", "Business.DB.SqlServer.SqlServerHelper");
//a.oInstance.Query();//报错了:因为oInstance当做是一个object类型,object类型是没有Query方法;C#语言是一种强类型语言;编译时决定你是什么类型,以左边为准;不能调用是因为编译器不允许;实际类型一定是SqlServerHelper;
//b.如果使用dynamic 作为类型的声明,在调用的时候,没有限制;
//c.dynamic :动态类型:不是编译时决定类型,避开编译器的检查;运行时决定是什么类型
//d.dynamic dInstance = Activator.CreateInstance(type);
//e.dInstance.Query();
//f.dInstance.Get(); //报错了--因为SqlServerHelper没有Get方法

4、类型转换

//4、类型转换
// SqlServerHelper helper = (SqlServerHelper)oInstance; //不建议这样转换--如果真实类型不一致--会报报错; 
IDBHelper helper = oInstance as IDBHelper;//如果类型一直,就转换,如果不一致;就返回null

5、调用方法

//5、调用方法
helper.Query();

三、反射创建对象封装

问题:反射创建对象代码很多。

其实除了dll的名称和类的全名称都是一样的代码,可以封装反射创建对象帮助类。
传入的参数都是字符串,可做成配置项,提高代码扩展性和灵活性,可以做到不修改代码而改变程序的功能。

1、反射创建对象封装

(1)创建SqlServerHelper的时候,没有依赖SqlServerHelper

(2)依赖的是两个字符串Business.DB.SqlServer.dll + Business.DB.SqlServer.SqlServerHelper,从配置文件读取。

(3)去掉个对细节的依赖的:依赖于抽象,不再依赖于细节;依赖倒置原则; 增强代码的稳定性;

using Business.DB.Interface;
using Microsoft.Extensions.Configuration;
using System;
using System.Reflection;

namespace MyReflecttion
{
    public class SimpleFactory
    {
        //创建SqlServerHelper的时候,没有依赖SqlServerHelper
        //依赖的是两个字符串Business.DB.SqlServer.dll + Business.DB.SqlServer.SqlServerHelper
        //去掉个对细节的依赖的:依赖于抽象,不再依赖于细节;依赖倒置原则; 增强代码的稳定性;
        public static IDBHelper CreateInstance()
        {  
            string ReflictionConfig = CustomConfigManager.GetConfig("ReflictionConfig"); 
            //Business.DB.SqlServer.SqlServerHelper,Business.DB.SqlServer.dll 
            string typeName = ReflictionConfig.Split(',')[0];
            string dllName = ReflictionConfig.Split(',')[1];

            //Assembly assembly = Assembly.LoadFrom("Business.DB.SqlServer.dll"); 
            //Type type = assembly.GetType("Business.DB.SqlServer.SqlServerHelper");

            Assembly assembly = Assembly.LoadFrom(dllName); 
            Type type = assembly.GetType(typeName);

            object? oInstance = Activator.CreateInstance(type);
            IDBHelper helper = oInstance as IDBHelper; 
            return helper; 
        }
    }

    public static class CustomConfigManager
    {
        //Core 读取配置文件:appsettings
        //1.Microsoft.Extensions.Configuration;
        //2.Microsoft.Extensions.Configuration.Json 
        public static string GetConfig(string key)
        {
            var builder = new ConfigurationBuilder().AddJsonFile("appsettings.json");  //默认读取  当前运行目录
            IConfigurationRoot configuration = builder.Build();
            string configValue = configuration.GetSection(key).Value;
            return configValue;
        }
    }
}

2. 配置文件

"ReflictionConfig": "Business.DB.Orcale.OrcaleHelper,Business.DB.Orcale.dll"

3、程序调用

如果公司来了一个新的技术经理:要将SqlServer换成MySql
(1)传统方式,必须要修改代码,然后必须要重新编译发布,步骤很多

(2)反射实现:断开了对普通类的依赖;依赖于配置文件+接口(抽象),做到了程序的可配置

(3)反射实现的步骤:按照接口约定实现一个Mysql帮助类库,Copy dll 文件到执行目录下,修改配置文件

IDBHelper helper1 = SimpleFactory.CreateInstance();
helper1.Query();

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

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

相关文章

JS之隐式转换与布尔判定

大家思考一下 [ ] [ ] ? 答案是空字符串 为什么呢? 当做加法运算的时候,发现左右两端存在非原始类型,也就是引用类型对象,就会对对象做隐式类型转换 如何执行的?或者说怎么查找的? 第一步&…

网络安全02--负载均衡下的webshell连接

目录 一、环境准备 1.1ubentu虚拟机一台,docker环境,蚁剑 1.2环境压缩包(文件已上传资源): 二、开始复原 2.1上传ubentu: 2.2解压缩 2.3版本20没有docker-compose手动下载,包已上传资源 …

netty源码前置一:Nio

NIO算是实现Reactor设计模式(单Selector 单工作线程)底层window用的是select,linux用的是epoll 网络NIO代码实现: public NIOServer(int port) throws Exception {selector Selector.open();serverSocket ServerSocketChannel.…

逻辑回归(Logistic Regression)和正则化

1.分类问题 案例: 在分类问题中,我们尝试预测的是结果是否属于某一个类(例如正确或错误)。分类问题的例子有:判断一封电子邮件是否是垃圾邮件;判断一次金融交易是否是欺诈;之前我们也谈到了肿瘤…

Python网络爬虫实战——实验4:Python爬虫代理的使用

【实验内容】 本实验主要介绍在爬虫采集数据的过程中代理的使用。 【实验目的】 1、掌握代理使用的基本场景; 2、解决IP封锁问题; 3、提高爬虫访问效率; 【实验步骤】 步骤1选择代理服务提供商 步骤2配置爬虫使用代理 步骤3 采集数据生成…

Ubuntu添加AppImage到桌面及应用程序菜单

将AppImage添加到桌面,以PicGo为例 效果: 在桌面创建PicGo.desktop文件,输入以下内容: [Desktop Entry] EncodingUTF-8 TypeApplication #应用名称 NamePicGo #图标路径 Icon/usr/local/AppImage/icons/PicGo.png #启动是否开启…

cmake设置Debug版本和Release版本的输出路径

项目背景:指定可执行文件和动态库输出路径都在bin目录文件夹下,由于项目中存在osg插件,然后我在项目中需要重写osg的插件,这时候就会遇到指定输出路径的问题,由于需要输出到osgPlugins-3.6.5文件夹下,所以使…

嘿嘿,vue之输出土味情话

有点好玩&#xff0c;记录一下。通过按钮调用网站接口&#xff0c;然后解构数据输出土味情话。 lovetalk.vue: <!--vue简单框架--> <template> <!-- 这是一个div容器&#xff0c;用于显示土味情话 --> <div class"talk"> <!-- 当点…

【现代密码学基础】详解完美安全与香农定理

目录 一. 介绍 二. 完美安全的密钥与消息空间 三. 完美安全的密钥长度 四. 最优的完美安全方案 五. 香农定理 &#xff08;1&#xff09;理论分析 &#xff08;2&#xff09;严格的正向证明 &#xff08;3&#xff09;严格的反向证明 六. 小结 一. 介绍 一次一密方案…

正则匹配 | 正则实际应用探索分享

这并不是一篇教正则基础的文章&#xff0c;其正则式不能对您进行使用后的结果负责&#xff0c;请以研究的眼光看待本篇文章。 技术就是懒人为了更好的懒才会想办法搞的东西&#xff0c;我最近因为某些原因需要频繁删除注释 我就想到通过替换的正则功能快速删除文件中的简单注…

Qslog开源库使用

Qslog源码下载地址&#xff1a;https://github.com/victronenergy/QsLog 1.QSLOG使用方式 &#xff08;1&#xff09;源码集成 在你的工程中&#xff0c;直接包含QsLog.pri文件&#xff0c;进行源码集成。当然你也可以包含QsLog.pri后&#xff0c;编译为xx.dll&#xff0c;在…

数据可视化练习

文章目录 试题示例 试题示例 绘制下图所示的表格 根据下表的数据&#xff0c;将班级名称一列作为x轴的刻度标签&#xff0c;将男生和女生两列的数据作为刻度标签对应的数值&#xff0c;使用bar()函数绘制下图所示的柱形图。 方式一 import numpy as np import matplotlib.p…

CUDA编程- - GPU线程的理解 thread,block,grid - 再次学习

GPU线程的理解 thread,block,grid 一、从 cpu 多线程角度理解 gpu 多线程1、cpu 多线程并行加速2、gpu多线程并行加速2.1、cpu 线程与 gpu 线程的理解&#xff08;核函数&#xff09;2.1.1 、第一步&#xff1a;编写核函数2.1.2、第二步&#xff1a;调用核函数&#xff08;使用…

跟着cherno手搓游戏引擎【12】渲染context和首个三角形

渲染上下文&#xff1a; 目的&#xff1a;修改WindowsWindow的结构&#xff0c;把glad抽离出来 WindowsWindow.h:新建m_Context #pragma once #include "YOTO/Window.h" #include <YOTO/Renderer/GraphicsContext.h> #include<GLFW/glfw3.h> #include…

iperf3网络带宽性能测试工具 局域网网络最大带宽高阶教程

iperf3 是一个 TCP, UDP, 和 SCTP (传输层协议)网络带宽测量工具&#xff0c;iperf 是一个用于主动测量 IP 网络上最大可用带宽的工具. 它支持与时间、协议和缓冲区相关的各种参数的调优. 对于每个测试&#xff0c;它报告测量的吞吐量/比特率(带宽), 丢包率和其他参数&#xff…

MySQL 覆盖索引

目录 一、什么是索引 二、索引的有哪些种类&#xff1f; 三、InnoDB的不同的索引组织结构是怎样的呢&#xff1f; 四、什么是覆盖索引 五、如何使用是覆盖索引&#xff1f; 六、如何确定数据库成功使用了覆盖索引呢 总结&#xff1a; 一、什么是索引 索引&#xff08;在 …

Log4j2-01-log4j2 hello world 入门使用

拓展阅读 Log4j2 系统学习 Logback 系统学习 Slf4j Slf4j-02-slf4j 与 logback 整合 SLF4j MDC-日志添加唯一标识 分布式链路追踪-05-mdc 等信息如何跨线程? Log4j2 与 logback 的实现方式 日志开源组件&#xff08;一&#xff09;java 注解结合 spring aop 实现自动输…

openssl3.2 - 测试程序的学习 - 准备openssl测试专用工程的模板

文章目录 openssl3.2 - 测试程序的学习 - 准备openssl测试专用工程的模板概述笔记工程中需要的openssl的库实现END openssl3.2 - 测试程序的学习 - 准备openssl测试专用工程的模板 概述 openssl3.2 - 测试程序的学习 整了几个test.c, 每开一个新的测试工程, 总要改这改那的. …

【RH850U2A芯片】Reset Vector和Interrupt Vector介绍

目录 前言 正文 1. 什么是Reset Vector 1.1 S32K144芯片的Reset Vector 1.2 RH850芯片的Reset Vector 2. 什么是Interrupt Vector 2.1 S32K144芯片的Interrupt Vector 2.2 RH850芯片的Interrupt Vector 3. Reset Vector等价于Interrupt Vector吗 4. 总结 前言 最近在…

uniapp微信小程序-input默认字的样式

需要的是这样的 问题 正常是在input框上面写样式就行&#xff0c;但是uniapp不起作用 解决 直接在input上写placeholder-style"color就解决了 <input class"findInput" type"text" placeholder"关键词查询"placeholder-style"co…