C#中的反射(Reflection)使用经典案例

文章目录

      • 1. 动态加载和调用类的方法
      • 2. 记录用户修改行为
      • 3. 调用私有构造函数
      • 4. 泛型类型的动态创建和使用
      • 5. 动态类型转换与检查
      • 6. 获取和设置私有、受保护成员
      • 7. 枚举程序集、模块、类型等信息
      • 8. 处理泛型类型参数
      • 9. 动态生成代码或动态编译
      • 10. 配置驱动的应用程序扩展
      • 注意事项:

C#中的反射(Reflection)是.NET框架提供的一种强大的运行时元编程机制,它允许程序在运行时获取类型信息、创建对象实例、调用方法、访问字段和属性等,而这些操作在编译时可能是未知的。以下是几个使用反射的典型场景:

1. 动态加载和调用类的方法

假设有一个库包含多个实现了同一接口的类,用户可以通过配置文件指定要使用的具体类名和方法名。通过反射,可以在运行时根据配置加载相应的类型,并调用指定的方法。

// 假设有个接口和其实现类
public interface ICalculator
{int Calculate(int a, int b);
}public class Adder : ICalculator
{public int Calculate(int a, int b) => a + b;
}// 配置中读取类名
string className = "Adder";
Type calculatorType = Type.GetType(className);// 创建实例并调用方法
ICalculator calculator = (ICalculator)Activator.CreateInstance(calculatorType);
int result = calculator.Calculate(3, 5);

2. 记录用户修改行为

如您提到的应用场景,系统需要记录用户修改了哪个实体类的哪些字段。通过反射,可以遍历实体类的所有属性,在用户修改后记录下变化的属性名和新旧值。

public class User
{public string Name { get; set; }public int Age { get; set; }// 其他属性...
}// 用户更新了一个User实例
var user = new User { Name = "OldName", Age = 30 };foreach (var property in properties)
{// 获取旧值(假设这是更改前的值)var oldValue = property.GetValue(user);// 模拟用户更改属性值if (property.Name == "Name"){user.Name = "NewName";}// 再次获取新值var currentValue = property.GetValue(user);// 如果旧值与当前值不相等,则记录变更if (!object.Equals(oldValue, currentValue) && property.CanRead && property.CanWrite){LogChange(property.Name, oldValue, currentValue);}
}

3. 调用私有构造函数

反射还可以用来调用非公开的构造函数,比如破坏单例模式时可能会用到:

public sealed class Singleton
{private static readonly Singleton instance = new Singleton();private Singleton() { }public static Singleton Instance => instance;// 通过反射破坏单例模式public static Singleton CreateAnotherInstance(){ConstructorInfo ctor = typeof(Singleton).GetConstructor(BindingFlags.Instance | BindingFlags.NonPublic,null, Type.EmptyTypes, null);return (Singleton)ctor.Invoke(null);}
}

4. 泛型类型的动态创建和使用

反射结合泛型,可以实现在不知道具体类型参数的情况下动态创建泛型类型实例:

public class GenericClass<T>
{public T Value { get; set; }
}Type genericType = typeof(GenericClass<>).MakeGenericType(typeof(string));
dynamic instance = Activator.CreateInstance(genericType);
instance.Value = "Hello, World!";

C#反射除了上述提到的几个典型应用场景外,还有以下一些常见的用途:

5. 动态类型转换与检查

  • 判断一个对象是否实现了某个接口或继承自某个类。
  • 在不知道具体类型的情况下,将对象动态转换为指定类型。
object obj = new MyDerivedClass();
Type type = obj.GetType();// 检查类型是否实现了某个接口
bool isDisposable = typeof(IDisposable).IsAssignableFrom(type);// 动态转换
if (type == typeof(MyDerivedClass))
{MyDerivedClass derivedObj = (MyDerivedClass)obj;// 使用转换后的对象...
}

6. 获取和设置私有、受保护成员

  • 反射可以访问私有字段、属性和方法,这在测试框架中特别有用,可以模拟对私有成员的调用或者验证其值。
public class MyClass
{private int myPrivateField;public void SetPrivateValue(int value){this.myPrivateField = value;}
}var instance = new MyClass();
FieldInfo field = typeof(MyClass).GetField("myPrivateField", BindingFlags.NonPublic | BindingFlags.Instance);
field.SetValue(instance, 42);  // 设置私有字段值int fieldValue = (int)field.GetValue(instance);  // 获取私有字段值

7. 枚举程序集、模块、类型等信息

  • 在大型应用程序中,可能需要枚举整个程序集中所有类型的元数据信息,比如获取所有的类名、特性(Attributes)等。
Assembly assembly = Assembly.GetExecutingAssembly();
foreach (Type type in assembly.GetTypes())
{Console.WriteLine($"Type: {type.FullName}");foreach (Attribute attribute in Attribute.GetCustomAttributes(type)){Console.WriteLine($"  Attribute: {attribute.GetType().Name}");}
}

8. 处理泛型类型参数

  • 反射可以帮助获取泛型类型的具体参数类型,并据此创建特定类型的实例。

9. 动态生成代码或动态编译

  • .NET Framework 和 .NET Core 提供了 System.Reflection.Emit 命名空间,允许开发者在运行时动态生成类型和方法。这对于实现AOP(面向切面编程)、动态代理或其他高级编程技术非常有用。

10. 配置驱动的应用程序扩展

  • 反射常用于构建插件式架构,根据配置文件加载不同插件(DLL)并在运行时动态加载并执行插件中的代码。

总之,C#反射是一个强大的工具,它允许程序在运行时获得关于类型和程序集的信息,并基于这些信息进行操作,极大地增强了应用程序的灵活性和适应性。但需要注意的是,过度使用反射可能会降低性能,应谨慎权衡其带来的便利性和潜在的成本。

注意事项:

  • 反射通常会带来性能开销,因为它涉及到运行时类型查找和动态方法调用。
  • 安全性方面,过度依赖反射可能导致代码容易受到攻击,例如绕过私有成员保护机制。
  • 静态编译优化对反射调用可能不适用,因此在对性能敏感的场合应谨慎使用反射。

python推荐学习汇总连接:
50个开发必备的Python经典脚本(1-10)

50个开发必备的Python经典脚本(11-20)

50个开发必备的Python经典脚本(21-30)

50个开发必备的Python经典脚本(31-40)

50个开发必备的Python经典脚本(41-50)
————————————————

​最后我们放松一下眼睛
在这里插入图片描述

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

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

武理多媒体信息共享平台的架构设计与实现

✍✍计算机编程指导师 ⭐⭐个人介绍&#xff1a;自己非常喜欢研究技术问题&#xff01;专业做Java、Python、微信小程序、安卓、大数据、爬虫、Golang、大屏等实战项目。 ⛽⛽实战项目&#xff1a;有源码或者技术上的问题欢迎在评论区一起讨论交流&#xff01; ⚡⚡ Java实战 |…

JNI笔记

JNI笔记 背景Demo代码JNI.javaMainActivity.javaAndroid.mkApplication.mkcom_stone_javacallc_JNI.hjavacallc.cbuild.gradle 背景 Demo代码 代码结构 JNI.java package com.stone.javacallc;/*** Created by stoneWang* Created on 2024/1/16* java调用C*/ public class …

【动态规划】【记忆化搜索】【C++算法】664. 奇怪的打印机

作者推荐 【矩阵快速幂】封装类及测试用例及样例 本文涉及知识点 动态规划 记忆化搜索 字符串 LeetCode:664 奇怪的打印机 有台奇怪的打印机有以下两个特殊要求&#xff1a; 打印机每次只能打印由 同一个字符 组成的序列。 每次可以在从起始到结束的任意位置打印新字符&am…

MacBook安装Storm与启动

MacBook安装Storm与启动 官方下载地址: https://storm.apache.org/downloads.html 官方下载 apache-storm-1.2.2.tar.gz MacBook Linux安装zookeeper 解压 tar -zxvf apache-storm-1.2.2.tar.gz先启动zookeeper cd zookeeper-3.4.12 ./bin/zkServer.sh start #查看状态 ./…

CentOS将磁盘剩余空间分配到已有分区

CentOS将磁盘剩余空间分配到已有分区 引growpartresize2fs 引 手里有台云服务&#xff0c;之前磁盘只有60G&#xff0c;在执行SQL语句时报错No space left on device. 通过df -h查看磁盘占用情况&#xff0c;确实所剩无几了 通过云服务后端控制台升级了下配置&#xff0c;将…

基于ArcGIS的晕线制作

在借助ArcGIS进行制图时&#xff0c;我们有时需要为矢量边界添加晕线&#xff0c;今天就来探索一下基于ArcGIS的晕线制作操作。 软件版本&#xff1a;ArcMap10.4.1 方法一&#xff1a;制作多环缓冲区 工具路径&#xff1a;Analysis Tools-Proximity-Mutiple Ring Buffer 思…

Vue3的使用

一 Vue3的变化 1.性能的提升 打包大小减少41% 初次渲染快55%, 更新渲染快133% 内存减少54% 2.源码的升级 使用Proxy代替defineProperty实现响应式 重写虚拟DOM的实现和Tree-Shaking 3.拥抱TypeScript Vue3可以更好的支持TypeScript 4.新的特性 Composition API&#…

入门指南:使用STM32微控制器进行ADC数据采集

使用STM32微控制器进行ADC&#xff08;模数转换器&#xff09;数据采集是嵌入式系统开发中常见的任务。本文将介绍如何通过STM32CubeMX和HAL库函数进行ADC数据采集&#xff0c;并提供相应的代码示例。 1. STM32CubeMX配置 首先&#xff0c;使用STM32CubeMX工具配置STM32微控制…

Vue3响应式系统(二)

Vue3响应式系统(一)https://blog.csdn.net/qq_55806761/article/details/135587077 六、嵌套的effect与effect栈。 什么场景会用到effect嵌套呢&#xff1f;听我娓娓道来。 就用Vue.js来说吧&#xff0c;Vue.js的渲染函数就是在effect中执行的&#xff1a; /*Foo组件*/ const…

使用mamba替换conda和anaconda配置环境安装软件

使用mamba替换miniconda和anaconda&#xff0c;原因是速度更快&#xff0c;无论是创建新环境还是激活环境 conda、mamba、anaconda都是蟒蛇的意思… 下载mambaforge wget https://github.com/conda-forge/miniforge/releases/latest/download/Mambaforge-Linux-x86_64.sh ba…

使用WAF防御网络上的隐蔽威胁之SSRF攻击

服务器端请求伪造&#xff08;SSRF&#xff09;攻击是一种常见的网络安全威胁&#xff0c;它允许攻击者诱使服务器执行恶意请求。与跨站请求伪造&#xff08;CSRF&#xff09;相比&#xff0c;SSRF攻击针对的是服务器而不是用户。了解SSRF攻击的工作原理、如何防御它&#xff0…

MongoDB-数据库文档操作(2)

任务描述 文档数据在 MongoDB 中的查询和删除。 相关知识 本文将教你掌握&#xff1a; 查询文档命令&#xff1b;删除文档命令。 查询文档 我们先插入文档到集合 stu1 &#xff1a; document([{ name:张小华, sex:男, age:20, phone:12356986594, hobbies:[打篮球,踢足球…