当前位置: 首页 > news >正文

C#反射的学习,反射的一些注意事项,反射的一些使用代码的实例

反射

  • c#反射
    • 八股文
    • 字段和属性的区别
    • 注意事项
    • 示例代码

c#反射

本文档写的的是C#中的反射常用的方式(附带示例代码)以及在使用的时候的一些注意事项。

八股文

C#中的反射是一种强大的机制,它允许在运行时动态地检查、访问和操作程序的元数据、类型信息和对象。以下是C#中反射常用的技巧和使用方式:

  1. 获取类型信息:使用Type类可以获取类型信息,如类名、命名空间、方法、字段等。你可以使用typeof操作符、GetType方法或通过对象实例获取类型信息。
  2. 创建对象:通过反射,你可以根据类型信息动态创建对象的实例,使用Activator.CreateInstance方法或Type的GetConstructor方法。
  3. 访问和修改字段和属性:反射允许你获取和设置对象的字段和属性值。你可以使用FieldInfo和PropertyInfo来实现。
  4. 调用方法:使用反射可以动态调用对象的方法。MethodInfo类允许你获得方法信息并调用它。
  5. 检查和调用构造函数:你可以使用反射检查和调用构造函数,使用ConstructorInfo类。
  6. 获取和设置属性值:使用PropertyInfo类可以获取和设置属性的值。
  7. 获取枚举成员:你可以使用反射获取枚举类型的成员,使用Enum.GetValues和Enum.GetNames方法。
  8. 处理泛型类型:反射允许你处理泛型类型,获取泛型参数,创建泛型类型的实例等。
  9. 动态装载程序集:你可以使用反射加载外部程序集,检查它们的内容,甚至实例化其中的类型。
  10. 自定义特性处理:你可以使用反射获取类型、方法、属性等的自定义特性(Attributes)信息,以实现元数据驱动的操作。
    使用反射时需要注意性能开销,因为它会涉及到运行时类型检查和动态方法调用,可能比直接编写静态代码更慢。因此,在正常情况下,应该尽量避免不必要的反射操作,特别是在性能敏感的应用中。

字段和属性的区别

字段没有get与set访问器

 public class MyClass
{private int myField; // 字段public int MyProperty // 属性{get { return myField; }set { myField = value; }}
}

注意事项

  1. 反射的参数建议使用nameof(类名.方法名),因为编译器会在编译时检查命名是否正确。
  2. 使用获取属性的方式去获取字段是会报空引用的
    获取属性使用:type.GetFields();type.GetField(name)
    获取字段使用:type.GetProperties(), type.GetProperty(name)
    获取方法使用:type.GetMethods(),type.GetMethod(name)
    获取接口使用:type.GetInterfaces()

示例代码

using System.Reflection;DateTime beforDT = System.DateTime.Now;FanShe();DateTime afterDT = System.DateTime.Now;
TimeSpan ts = afterDT.Subtract(beforDT);
Console.WriteLine("DateTime总共花费{0}ms.", ts.TotalMilliseconds);
Console.ReadKey();static void FanShe()
{//创建对象Man manObj = new Man();Type type = manObj.GetType();//获取所有字段Console.WriteLine("\n获取公开的字段");FieldInfo[] fieldInfos = type.GetFields();for (int f = 0; f < fieldInfos.Count(); f++){Console.WriteLine("公开的字段有:" + fieldInfos[f].Name);}Console.WriteLine("\n获取特定字段并修改字段:");//字段与属性的区别,字段无getset访问器,属性有。FieldInfo fieldInfo_id = type.GetField(nameof(Animal.Age));fieldInfo_id.SetValue(manObj, 123);//设置Age为123Console.WriteLine("第一次修改是age字段是:" + fieldInfo_id.GetValue(manObj));//打印出AgefieldInfo_id.SetValue(manObj, 17);//设置Age为123Console.WriteLine("第二次修改是age字段是:" + fieldInfo_id.GetValue(manObj));//打印出AgeConsole.WriteLine("\n所有属性:");PropertyInfo[] properties = type.GetProperties();foreach (PropertyInfo property in properties){Console.WriteLine(property.Name);}Console.WriteLine("\n获取特定属性并修改属性");PropertyInfo propertie_name = type.GetProperty(nameof(Man.Nationality));propertie_name.SetValue(manObj, "China");Console.WriteLine("第一次修改后的属性是" + propertie_name.GetValue(manObj));propertie_name.SetValue(manObj, "Japan");Console.WriteLine("第二次修改后的属性是" + propertie_name.GetValue(manObj));Console.WriteLine("/n获取实现的接口");Type[] interfaces = type.GetInterfaces();foreach (Type iface in interfaces){Console.WriteLine(iface.Name);}Console.WriteLine("是否为空的判断");if (type.GetProperty(nameof(Man.Colour)) == null){Console.WriteLine($"{nameof(Man.Colour)}not found.");return;}PropertyInfo manColour = type.GetProperty(nameof(Man.Colour));if (!manColour.CanWrite){Console.WriteLine("Cannot write to Man.Colour property.");return;}manColour.SetValue(manObj, "yellow");//设置属性Console.WriteLine($"{nameof(manObj.Colour)}{manObj.Colour}");//获取到公开的方法MethodInfo[] methodInfos = type.GetMethods();for (int i = 0; i < methodInfos.Count(); i++){Console.WriteLine(methodInfos[i].Name);}Console.WriteLine("\n调用无参的方法");MethodInfo methodInfo_popop = type.GetMethod(nameof(Man.Popop));methodInfo_popop.Invoke(manObj, null);Console.WriteLine("\n调用有参的方法");MethodInfo methodInfo_eatFood = type.GetMethod(nameof(Man.EatFood));methodInfo_eatFood.Invoke(manObj, new object[] { "香蕉", 123 });Console.WriteLine("\n调用无参数有返回值的方法");MethodInfo methodInfo_Speed = type.GetMethod(nameof(Man.Speed));object money = methodInfo_Speed.Invoke(manObj, new object[] { 123 });Console.WriteLine($"反射方法的返回值是:{money}");Console.WriteLine("\n调用接口无返回值无参数");MethodInfo speakingEnglishMethod = type.GetInterface(nameof(ILanguage)).GetMethod(nameof(Animal.SpeakingEnglish));speakingEnglishMethod.Invoke(manObj, null); // 输出: I can speak English.Console.WriteLine("\n调用接口无返回值有参数");MethodInfo speakJapaneseMethod = type.GetInterface(nameof(ILanguage)).GetMethod(nameof(Animal.SpeakJapanese));Console.WriteLine("返回是:" + "返回值是:" + speakJapaneseMethod.Invoke(manObj, null));Console.WriteLine("\n调用接口有返回值有参数");MethodInfo speakChineseMethod = type.GetInterface(nameof(ILanguage)).GetMethod(nameof(Animal.SpeakChinese));Console.WriteLine("返回值是:" + speakChineseMethod.Invoke(manObj, new object[] { "你好" }));Console.WriteLine("\n当与父类中有相同的方法的时候,调用父类中的同名方法");MethodInfo animalDoSexMethod = type.BaseType.GetMethod(nameof(Animal.DoSex));Console.WriteLine("父类中的方法" + animalDoSexMethod.Invoke(manObj, new object[] { "hei heihei" }));Console.WriteLine("\n当与父类中有相同的方法的时候,调用子类的同名方法");MethodInfo manDoSexMethod = type.GetMethod(nameof(Man.DoSex));Console.WriteLine("子类中的方法" + manDoSexMethod.Invoke(manObj, new object[] { "ha hhhaa" }));Console.WriteLine("\n子类调用重写的方法,\n当子类重写了父类的方法时,您可以通过子类类型来反射调用它。但是需要注意的是,在这种情况下,将始终调用子类中的方法版本,而不是父类中的版本。");MethodInfo drawMethod = type.GetMethod(nameof(Man.Draw));drawMethod.Invoke(manObj, new object[] { "山水" });}public class Man : Animal, ILanguage
{/// <summary>/// 国籍/// </summary>public string Nationality { get; set; }/// <summary>/// 肤色/// </summary>public string Colour { get; set; }/// <summary>/// 瞳孔颜色/// </summary>public string PupilColor;/// <summary>/// 说话/// </summary>/// <param name="word"></param>public void Say(string word){Console.WriteLine("我说:" + word);}/// <summary>/// 花钱/// </summary>public int Speed(int money){Console.WriteLine($"本次消费的金额是:{money}元。");return money;}/// <summary>/// 读书/// </summary>private void ReadBook(){Console.WriteLine("Reading book");}/// <summary>/// 交配/// </summary>/// <returns></returns>public new string DoSex(string targetName){return $"is sexing with {targetName} ";}/// <summary>/// 画画/// </summary>/// <param name="drawName"></param>public override void Draw(string drawName){Console.WriteLine($"这副{drawName}被我画好了");}}/// <summary>
/// 动物
/// </summary>
public class Animal : ILanguage
{/// <summary>/// 序号/// </summary>public int ID { get; set; }/// <summary>/// 姓名/// </summary>public string Name { get; set; }/// <summary>/// 性别/// </summary>public string Sex;/// <summary>/// 年龄/// </summary>public int Age;/// <summary>/// 是否开心/// </summary>public bool isHappy;/// <summary>/// 吃饭/// </summary>/// <param name="foodName"></param>/// <param name="foodcount"></param>public void EatFood(string foodName, int foodcount){Console.WriteLine($"我吃了{foodcount}{foodName}");}/// <summary>/// 拉屎/// </summary>/// <returns></returns>public string Popop(){Console.WriteLine("is popoping");return "poping";}/// <summary>/// 交配/// </summary>/// <returns></returns>public string DoSex(string targetName){return $"is sexing with {targetName} ";}public void SpeakingEnglish(){Console.WriteLine("i am speaking English, no return value and parameters.");}public string SpeakJapanese(){return "Speaking Japanese wrod";}public string SpeakChinese(string wrod){return $"Chinese wrod:{wrod}";}/// <summary>/// 画画/// </summary>/// <param name="drawName"></param>public virtual void Draw(string drawName){Console.WriteLine($"我正在画{drawName}");}}/// <summary>
/// 语言的接口
/// </summary>
public interface ILanguage
{/// <summary>/// 说英语/// </summary>void SpeakingEnglish();string SpeakJapanese();string SpeakChinese(string wrod);}

相关文章:

  • VSCode 如何设置背景图片
  • Linux启动故障排错
  • 使用脚本整合指定文件/文件夹,执行定制化 ESLint 命令
  • LiveMeida视频接入网关
  • [JavaWeb]——获取请求参数的方式(全面!!!)
  • 基于tpshop开发多商户源码支持手机端+商家+门店 +分销+淘宝数据导入+APP+可视化编辑
  • Centos7下生成https自签名证书
  • 【Linux】安装使用Nginx负载均衡,并且部署前端项目
  • 常用编程语言排行与应用场景汇总(2023.10)
  • NOIP2023模拟8联测29 C. 蛋糕
  • 【Django】项目模型
  • 第四章 应用SysML基本特性集的汽车示例 P2(断更)|系统建模语言SysML实用指南学习
  • MATLAB算法实战应用案例精讲-【图像处理】机器视觉(基础篇)(八)
  • CSS3中的字体和文本样式
  • FreeRTOS_信号量之互斥信号量
  • download使用浅析
  • input实现文字超出省略号功能
  • iOS筛选菜单、分段选择器、导航栏、悬浮窗、转场动画、启动视频等源码
  • java B2B2C 源码多租户电子商城系统-Kafka基本使用介绍
  • JavaScript服务器推送技术之 WebSocket
  • React 快速上手 - 06 容器组件、展示组件、操作组件
  • 阿里研究院入选中国企业智库系统影响力榜
  • 记录:CentOS7.2配置LNMP环境记录
  • 技术:超级实用的电脑小技巧
  • 世界上最简单的无等待算法(getAndIncrement)
  • 算法-图和图算法
  • media数据库操作,可以进行增删改查,实现回收站,隐私照片功能 SharedPreferences存储地址:
  • 【云吞铺子】性能抖动剖析(二)
  • PostgreSQL之连接数修改
  • 阿里云移动端播放器高级功能介绍
  • ​ 轻量应用服务器:亚马逊云科技打造全球领先的云计算解决方案
  • (1)Map集合 (2)异常机制 (3)File类 (4)I/O流
  • (5)STL算法之复制
  • (echarts)echarts使用时重新加载数据之前的数据存留在图上的问题
  • (react踩过的坑)antd 如何同时获取一个select 的value和 label值
  • (附程序)AD采集中的10种经典软件滤波程序优缺点分析
  • (附源码)spring boot智能服药提醒app 毕业设计 102151
  • (七)c52学习之旅-中断
  • (十一)手动添加用户和文件的特殊权限
  • (万字长文)Spring的核心知识尽揽其中
  • (详细版)Vary: Scaling up the Vision Vocabulary for Large Vision-Language Models
  • (一)ClickHouse 中的 `MaterializedMySQL` 数据库引擎的使用方法、设置、特性和限制。
  • ..thread“main“ com.fasterxml.jackson.databind.JsonMappingException: Jackson version is too old 2.3.1
  • .NET Core 成都线下面基会拉开序幕
  • .net core开源商城系统源码,支持可视化布局小程序
  • .NET 简介:跨平台、开源、高性能的开发平台
  • .NET 中让 Task 支持带超时的异步等待
  • [ 隧道技术 ] 反弹shell的集中常见方式(四)python反弹shell
  • [20170728]oracle保留字.txt
  • [20180312]进程管理其中的SQL Server进程占用内存远远大于SQL server内部统计出来的内存...
  • [AHOI2009]中国象棋 DP,递推,组合数
  • [Android]RecyclerView添加HeaderView出现宽度问题
  • [BZOJ1053][HAOI2007]反素数ant
  • [BZOJ1089][SCOI2003]严格n元树(递推+高精度)
  • [C#]C#学习笔记-CIL和动态程序集