【C#进阶】C# 反射
| 序号 | 系列文章 |
|---|---|
| 11 | 【C#基础】C# 预处理器指令 |
| 12 | 【C#基础】C# 文件与IO |
| 13 | 【C#进阶】C# 特性 |
文章目录
- 前言
- 1,反射的概念
- 2,使用反射访问特性
- 3,反射的用途
- 4,反射的优缺点比较
- 4.1 优点:
- 4.2 缺点:
- 5,System.Reflection 命名空间
- 5.1 获取程序集中的信息
- 5.2 获取程序集中的类型
- 5.3 获取程序集中的成员
- 5.4 创建类型的实例对象
- 结语
前言
✋ 大家好,我是writer桑,本章为大家介绍 C# 中的反射。
1,反射的概念
反射指的是程序可以访问,检测和修改它本身状态或行为的一种行为。 其中访问的目标包括程序集1、模块和类型对象等。可以使用反射动态地创建类型的实例,将类型绑定到现有对象,或从现有对象中获取类型,然后调用其方法或访问器字段和属性。反射行为也常常用来访问应用在程序上的特性。
代码示例:(简单展示)
using System;
using System.Reflection;public class Example
{static void Main(){// 使用反射获取程序集的信息:Assembly info = typeof(int).Assembly;Console.WriteLine(info);}
}
运行结果:

在上例中,使用 typeof 方法获取已加载的 int 程序集的完整名称。
2,使用反射访问特性
在前面的一章中,我们讨论到了 C# 使用反射访问特性的操作。在本章中就可以使用反射的操作来访问 Example 类中的元数据。
代码示例:
using System;[System.AttributeUsage(System.AttributeTargets.Class |System.AttributeTargets.Struct)
]
public class AuthorAttribute : System.Attribute
{public string name; public double age;// 构造函数public AuthorAttribute(string name){this.name = name;age = 11;}
}[Author("writer桑", age = 21)]
public class Example
{// Example类成员
}public class Program
{static void Main(){// 访问 Example 类应用的特性 Type type = typeof(Example);// 遍历输出 foreach(Object attributes in type.GetCustomAttributes(true)){AuthorAttribute author = (AuthorAttribute)attributes;Console.WriteLine(author.age);Console.WriteLine(author.name); }}
}
运行结果:

3,反射的用途
反射的用途可以总结为以下几点:
- 需要访问程序中的元数据的特性时。(点击了解更多)
- 检查和实例化程序集中的类型时。
- 在运行时构建新的类型,比如使用 System.Reflection.Emit 中的类。(点击了解更多)
- 执行后期绑定,访问在运行时创建的类型上的方法时。(点击了解更多)
4,反射的优缺点比较
反射的优缺点比较:
4.1 优点:
- 反射是运行期的操作,提高了程序的灵活性和扩展性。
- 降低耦合度2,提高自适应能力。
- 允许动态的创建和使用对象,无需提前硬编码3目标对象。
4.2 缺点:
- 性能较低,反射是运行期4的代码,在性能方面不如直接的编译型5代码。
- 可读性较低,使用反射会使得程序本身的逻辑变得复杂,在可读性方面不如直接的代码来的简洁。
- 维护成本变高,反射是一种绕过了源代码的技术, 因而在维护的方面难度较高。
5,System.Reflection 命名空间
System.Reflection 命名空间中包含通过检测托管代码中程序集、模块、成员、参数和其他实体的元数据来检索其相关信息的类型。同时也可以用于操作加载类型的实例,例如钩子函数6或调用方法。在 C# 中,实现反射操作常常需要用到 System.Reflection 命名空间中的类和方法。
列举一些 System.Reflection 命名空间中常用的反射操作:
5.1 获取程序集中的信息
System.Reflection 命名空间中的 Assembly.FullName 等属性可以用来获取程序集中的信息。
代码示例:
using System;
using System.Reflection;public class Example
{private int factor;public Example(int f){factor = f;}public int SampleMethod(int x){Console.WriteLine($"实例方法的执行:({x})");return x * factor;}public static void Main(){Assembly assem = typeof(Example).Assembly;Console.WriteLine($"程序集的全程:{assem.FullName}");// 可以使用 AssemblyName 类型解析完整名称。AssemblyName assemName = assem.GetName();Console.WriteLine($"名称: {assemName.Name}");//从程序集创建一个对象,并传入正确的数字//构造函数的参数类型。Object o = assem.CreateInstance("Example", false, BindingFlags.ExactBinding, null, new Object[] { 2 }, null, null);// 对对象的实例方法进行晚绑定调用。MethodInfo m = assem.GetType("Example").GetMethod("SampleMethod");Object ret = m.Invoke(o, new Object[] { 42 });Console.WriteLine($"示例方法的返回值为:{ret}");Console.WriteLine($"程序集入口点:{assem.EntryPoint}");}
}
运行结果:

5.2 获取程序集中的类型
System.Reflection 命名空间中的 Assembly.GetExportedTypes 方法可以用来获取程序集中定义的公共类型,这些公共类型在程序集外可见。
代码示例:
using System;
using System.Reflection;public class PublicClass
{public class PublicNestedClass { }protected class ProtectedNestedClass { }internal class FriendNestedClass { }private class PrivateNestedClass { }
}public class Example
{public static void Main(){// 获取程序集中定义的公共类型 foreach (Type t in typeof(Example).Assembly.GetExportedTypes()){Console.WriteLine(t);}}
}
运行结果:

5.3 获取程序集中的成员
System.Reflection 命名空间中的 MemberInfo 类中的属性和方法可以用来获取有关成员属性的信息并提供对成员元数据的访问权限。
代码示例:
using System;
using System.Reflection;public class Example
{// 显示应用到指定成员的自定义属性 public static void DisplayAttributes(Int32 indent, MemberInfo mi){// 获取自定义属性集;如果不存在,则返回。object[] attrs = mi.GetCustomAttributes(false);if (attrs.Length == 0) { return; }// 显示应用于该成员的自定义属性。Display(indent + 1, "属性:");foreach (object o in attrs){Display(indent + 2, "{0}", o.ToString());}}// 显示一个缩进的格式化字符串。 public static void Display(Int32 indent, string format, params object[] param){Console.Write(new string(' ', indent * 2));Console.WriteLine(format, param);}public static void Main(){//该变量保存缩进的数量, 显示每一行信息时使用。Int32 indent = 0;// 显示加载到这个 AppDomain 第一个 程序集的信息。Assembly b = AppDomain.CurrentDomain.GetAssemblies()[0];Display(indent, "程序集: {0}", b);// 显示从此程序集导出的 第一个 类型的相关信息。 indent += 1;Type t = b.GetExportedTypes()[0];Display(0, "");Display(indent, "类型: {0}", t);// 遍历显示成员及其自定义属性。indent += 1;foreach (MemberInfo mi in t.GetMembers()) // GetMembers 方法{Display(indent, "成员: {0}", mi.Name);DisplayAttributes(indent, mi);// 如果成员是一个方法,显示它的参数信息。if (mi.MemberType == MemberTypes.Method){foreach (ParameterInfo pi in ((MethodInfo)mi).GetParameters()){Display(indent + 1, "参数: 类型={0}, 名字={1}", pi.ParameterType, pi.Name);}}// 如果成员是一个属性,显示关于属性的访问方法的信息。 if (mi.MemberType == MemberTypes.Property){foreach (MethodInfo am in ((PropertyInfo)mi).GetAccessors()){Display(indent + 1, "访问器方法: {0}", am);}}}}
}
运行结果:

5.4 创建类型的实例对象
System.Reflection 空间中的 Assembly.CreateInstance 方法可以用来获取包含当前执行的代码的程序集,以此来创建类型的实例对象。
代码示例:
using System;
using System.Reflection;public class Person
{private string _name;public Person(){ }public Person(string name){this._name = name;}public string Name{get { return this._name; }set { this._name = value; }}public override string ToString(){return this._name;}
}public class Example
{public static void Main(){Assembly assem = typeof(Person).Assembly;// 创建 Person 类的实例化对象 Person p = (Person)assem.CreateInstance("Person");if (!(p == null)){p.Name = "John";Console.WriteLine($"实例化值为'{p}'的{p.GetType().Name}对象");}else{Console.WriteLine("无法实例化Person对象。");}}
}
运行结果:

点击了解更多 System.Reflection 命名空间的使用。
结语
👋 以上就是关于 C# 反射的介绍啦,希望对大家有所帮助。感谢大家的支持。
程序集(assembly):是一个及一个以上托管模块,以及一些资源文件的逻辑组合。在 .NET 中,dll与exe文件都是程序集。 ↩︎
耦合性(或称耦合力或耦合度):是一种软件度量,是指一程序中,模块及模块之间信息或参数依赖的程度。 ↩︎
硬编码:是将数据直接嵌入到程序或其他可执行对象的源代码中的软件开发实践,与从外部获取数据或在运行时生成数据不同。 ↩︎
运行期:是把编译后的文件交给计算机执行,直到程序运行结束。 ↩︎
编译期:是指把源码交给编译器编译成计算机可以执行的文件的过程。 ↩︎
钩子函数:是 Windows 消息处理机制的一部分,是指在程序正常运行中接受信息之前预先启动的函数,用来检查和修改传给该程序的信息,(钩子)实际上是一个处理消息的程序段,通过系统调用,把它挂入系统。 ↩︎
相关文章:
【C#进阶】C# 反射
序号系列文章11【C#基础】C# 预处理器指令12【C#基础】C# 文件与IO13【C#进阶】C# 特性文章目录前言1,反射的概念2,使用反射访问特性3,反射的用途4,反射的优缺点比较4.1 优点:4.2 缺点:5,System…...
公网NAT网关与VPC NAT网关介绍与实践
NAT网关介绍 NAT网关是一种网络地址转换服务,提供NAT代理(SNAT和DNAT)能力。 公有云NAT分为公网NAT网关和VPC NAT网关。 1)公网NAT网关:提供公网地址转换服务。 2)VPC NAT网关:提供私网地址转换…...
Windows中UWP、WPF和Windows窗体的区别
Windows 中开发应用(或者可以说客户端)有三种方法: UWP(Universal Windows Platform)、WPF(Windows Presentation Foundation)和 Windows 窗体(Win Forms)。这三种方法在…...
Flink从入门到精通系列(一)
1、Flink概述 Apache Flink 是一个框架和分布式处理引擎,用于在, 无边界和有边界数据流上进行有状态的计算 ,Flink 能在所有常见集群环境中运行,并能以内存速度和任意规模进行计算。 Apache Flink 功能强大,支持开发…...
云原生应用风险介绍
本博客地址:https://security.blog.csdn.net/article/details/129303616 一、传统风险 传统风险主要是注入、敏感数据泄露、跨站脚本、配置错误等等,这些传统的安全风险在云原生应用中也是存在的,这里就不具体展开说了。 二、云原生应用架…...
什么是测试用例设计?
前言 想要进行测试自动化的团队都会遇到这个问题:自动化的成功和编码能力有多大的关联?现在更多的招聘信息越来越偏重于对测试人员的编程能力的要求,似乎这个问题的答案是极大的正关联性。 测试人员可以将编码能力用于与测试相关的各种目的…...
数据分析:基于K-近邻(KNN)对Pima人糖尿病预测分析
数据分析:基于K-近邻(KNN)对Pima人糖尿病预测分析 作者:AOAIYI 作者简介:Python领域新星作者、多项比赛获奖者:AOAIYI首页 😊😊😊如果觉得文章不错或能帮助到你学习,可以点赞&#x…...
Kettle体系结构及源码解析
介绍 ETL是数据抽取(Extract)、转换(Transform)、装载(Load)的过程。Kettle是一款国外开源的ETL工具,有两种脚本文件transformation和job,transformation完成针对数据的基础转换&…...
大数据 | (二)SSH连接报错Permission denied
大数据 | (三)centos7图形界面无法执行yum命令:centos7图形界面无法执行yum命令 哈喽!各位CSDN的朋友们大家好! 今天在执行Hadoop伪分布式安装时,遇到了一个问题,在此跟大家分享, …...
前端——6.文本格式化标签和<div>和<span>标签
这篇文章,我们来讲一下HTML中的文本格式化标签 目录 1.文本格式化标签 1.1介绍 1.2代码演示 1.3小拓展 2.div和span标签 2.1介绍 2.2代码演示 2.3解释 3.小结 1.文本格式化标签 在网页中,有时需要为文字设置粗体、斜体和下划线等效果…...
浅谈Xpath注入漏洞
目录 知识简介 攻击简介 基础语法 语法演示 漏洞简介 漏洞原理 漏洞复现 Xpath盲注 知识简介 攻击简介 XPath注入攻击是指利用XPath 解析器的松散输入和容错特性,能够在 URL、表单或其它信息上附带恶意的XPath 查询代码,以获得权限信息的访问权…...
Oracle LogMiner分析归档日志
目录:Oracle LogMiner分析归档日志一、准备测试环境1、开启数据库归档日志2、打开数据库最小附加日志3、设置当前session时间日期格式二、创建测试数据1、创建数据2、数据落盘三、日志发掘测试挖掘在上次归档的Redo Log File1.确定最近归档的Redo Log File2.指定要分…...
趣味三角——第15章——傅里叶定理
第15章 傅里叶定理(Fourier’s Theorem) Fourier, not being noble, could not enter the artillery, although he was a second Newton. (傅立叶出生并不高贵,因此按当时的惯例进不了炮兵部队,虽然他是第二个牛顿。) —Franois Jean Dominique Arag…...
市场营销的核心是什么?
之所以写下「市场营销的核心是什么?」这篇文章,是因为这几天刚读完了《经理人参阅:市场营销》这本书。作为一个有着近十年工作经验的市场营销从业人员,看完这本书也产生了很多新的想法,也想记录一下,遂成此…...
c/cpp - 多线程/进程 多进程
c/cpp - 多线程/进程 多进程多进程创建多进程进程等待多进程 宏观上 两个进程完全并发的 父子进程具有互相独立的进程空间 父进程结束,不影响子进程的执行 创建多进程 #include <sys/types.h> #include <unistd.h> #include <stdio.h>int main()…...
MySQL必知必会 | 存储过程、游标、触发器
使用存储过程 存储过程 简单来说就是为了以后的使用而保存的一条或多条MySQL语句的集合。 我觉得就是封装了一组sql语句 为什么需要存储过程(简单来说就是,简单、安全、高性能 通过把处理封装在容易使用的单元中,简化复杂操作所有开发人员…...
优化Facebook广告ROI的数据驱动方法:从投放到运营
“投放广告并不是最终的目的,关键在于如何最大程度地利用数据驱动的方法来提高广告投放的回报率(ROI)”Facebook广告是现代数字营销中最为常见和重要的广告形式之一。但是,要让Facebook广告真正发挥作用,需要通过数据驱…...
动态规划入门经典问题讲解
最近开始接触动态规划问题,以下浅谈(或回顾)一下这些问题的求解过程。解题思路对于动态规划问题,由于最终问题的求解需要以同类子问题作为基础,故需要定义一个dp数组(一维或二维)来记录问题求解…...
快速入门深度学习1(用时1h)
速通《动手学深度学习》1写在最前面0.内容与结构1.深度学习简介1.1 问题引入1.2 思路:逆向思考1.3 跳过1.4 特点1.5 小结2.预备知识(MXNet版本,学错了。。。。)2.1 获取和运行本书的代码2.2 数据操作2.2.1 略过2.2.2 小结2.3 自动…...
PaddleOCR关键信息抽取(KIE)的训练(SER训练和RE训练)错误汇总
1.SER训练报错: SystemError: (Fatal) Blocking queue is killed because the data reader raises an exception 1.1.问题描述 在执行训练任务的时候报错 单卡训练 python3 tools/train.py -c train_data/my_data/ser_vi_layoutxlm_xfund_zh.yml错误信息如下: T…...
React第五十七节 Router中RouterProvider使用详解及注意事项
前言 在 React Router v6.4 中,RouterProvider 是一个核心组件,用于提供基于数据路由(data routers)的新型路由方案。 它替代了传统的 <BrowserRouter>,支持更强大的数据加载和操作功能(如 loader 和…...
Java - Mysql数据类型对应
Mysql数据类型java数据类型备注整型INT/INTEGERint / java.lang.Integer–BIGINTlong/java.lang.Long–––浮点型FLOATfloat/java.lang.FloatDOUBLEdouble/java.lang.Double–DECIMAL/NUMERICjava.math.BigDecimal字符串型CHARjava.lang.String固定长度字符串VARCHARjava.lang…...
如何将联系人从 iPhone 转移到 Android
从 iPhone 换到 Android 手机时,你可能需要保留重要的数据,例如通讯录。好在,将通讯录从 iPhone 转移到 Android 手机非常简单,你可以从本文中学习 6 种可靠的方法,确保随时保持连接,不错过任何信息。 第 1…...
pikachu靶场通关笔记22-1 SQL注入05-1-insert注入(报错法)
目录 一、SQL注入 二、insert注入 三、报错型注入 四、updatexml函数 五、源码审计 六、insert渗透实战 1、渗透准备 2、获取数据库名database 3、获取表名table 4、获取列名column 5、获取字段 本系列为通过《pikachu靶场通关笔记》的SQL注入关卡(共10关࿰…...
CSS | transition 和 transform的用处和区别
省流总结: transform用于变换/变形,transition是动画控制器 transform 用来对元素进行变形,常见的操作如下,它是立即生效的样式变形属性。 旋转 rotate(角度deg)、平移 translateX(像素px)、缩放 scale(倍数)、倾斜 skewX(角度…...
PostgreSQL——环境搭建
一、Linux # 安装 PostgreSQL 15 仓库 sudo dnf install -y https://download.postgresql.org/pub/repos/yum/reporpms/EL-$(rpm -E %{rhel})-x86_64/pgdg-redhat-repo-latest.noarch.rpm# 安装之前先确认是否已经存在PostgreSQL rpm -qa | grep postgres# 如果存在࿰…...
学习一下用鸿蒙DevEco Studio HarmonyOS5实现百度地图
在鸿蒙(HarmonyOS5)中集成百度地图,可以通过以下步骤和技术方案实现。结合鸿蒙的分布式能力和百度地图的API,可以构建跨设备的定位、导航和地图展示功能。 1. 鸿蒙环境准备 开发工具:下载安装 De…...
PydanticAI快速入门示例
参考链接:https://ai.pydantic.dev/#why-use-pydanticai 示例代码 from pydantic_ai import Agent from pydantic_ai.models.openai import OpenAIModel from pydantic_ai.providers.openai import OpenAIProvider# 配置使用阿里云通义千问模型 model OpenAIMode…...
Win系统权限提升篇UAC绕过DLL劫持未引号路径可控服务全检项目
应用场景: 1、常规某个机器被钓鱼后门攻击后,我们需要做更高权限操作或权限维持等。 2、内网域中某个机器被钓鱼后门攻击后,我们需要对后续内网域做安全测试。 #Win10&11-BypassUAC自动提权-MSF&UACME 为了远程执行目标的exe或者b…...
篇章一 论坛系统——前置知识
目录 1.软件开发 1.1 软件的生命周期 1.2 面向对象 1.3 CS、BS架构 1.CS架构编辑 2.BS架构 1.4 软件需求 1.需求分类 2.需求获取 1.5 需求分析 1. 工作内容 1.6 面向对象分析 1.OOA的任务 2.统一建模语言UML 3. 用例模型 3.1 用例图的元素 3.2 建立用例模型 …...
