.NET知识梳理——2.反射
1. 反射
1.1 DLL-IL-Metadata-反射
DLL:程序集,包含IL 和Metadada
IL:面向对象中间语言(不太好阅读)
Metadata描述了dll、exe中的各种类、属性、方法、参数等信息。
反射 Reflection: .NET Framework提供的帮助类库,可以读取Metadata。
C# 高级语言经过编译器编译生成DLL/EXE,DLL/EXE中包含了Metadata和IL,CLR先读取DLL/EXE中的Metadata,然后JIT进行二次编译,编译成机器码。
1.2 反射加载DLL,读取类、方法、特性
1.2.1 加载DLL
Assembly assembly = Assembly.Load("XF.DB.SqlServer");//动态加载,需要提供完整的DLL名,不需要后缀,从exe所在的路径进行查找
Assembly assembly2 = Assembly.LoadFile(@"C:\HXF_CODE\02.Code\05.NET Code\XF.High.NET.Study\XF.DB.SqlServer\bin\Debug\XF.DB.Sqlserver.dll");
Assembly assembly3 = Assembly.LoadFrom("XF.DB.SqlServer.dll");
Assembly assembly4 = Assembly.LoadFrom(@"C:\HXF_CODE\02.Code\05.NET Code\XF.High.NET.Study\XF.DB.SqlServer\bin\Debug\XF.DB.Sqlserver.dll");
1.2.2 读取类并创建对象
Type type = assembly.GetType("XF.DB.SqlServer.SqlServerHelper");//获取类型,需要提供完整的类型名称
object sqlServerHelper = Activator.CreateInstance(type);
IDBHelper dbHelper = sqlServerHelper as IDBHelper;
dbHelper.Query();
2.2.创建多构造函数对象:
object ctor1 = Activator.CreateInstance(type);
object ctor2 = Activator.CreateInstance(type, new object[] { 123 });
object ctor3 = Activator.CreateInstance(type, new object[] { "Olive" });
1.3 反射创建对象,反射+简单工厂+配置文件
程序可配置,通过配置文件自动切换
实现类必须是事先已有的,且存在运行目录下
没有写死类型,通过配置文件执行,反射创建
可扩展:不修改原有代码,只是增加新的实现,修改配置即可支持新功能
反射动态加载、创建对象,与配置文件结合。
private static string typeStr = ConfigurationManager.AppSettings["IDBHelperConfig"];
//反射动态加载、创建对象结合配置文件
{
string[] typeArr = typeStr.Split(',');
Assembly assembly1 = Assembly.Load(typeArr[1]);
Type type = assembly1.GetType(typeArr[0]);
foreach (var ctor in type.GetConstructors())
{
Console.WriteLine(ctor.Name);
foreach (var parameter in ctor.GetParameters())
{
Console.WriteLine(parameter.ParameterType);
}
}
object ctor1 = Activator.CreateInstance(type);
object ctor2 = Activator.CreateInstance(type, new object[] { 123 });
object ctor3 = Activator.CreateInstance(type, new object[] { "Olive" });
}
1.4 选修:破坏单例 创建泛型
1.4.1 反射破坏单例
反射破坏单例(调用私有的构造函数)
//反射破坏单例(调用私有的构造函数)
Assembly assembly5 = Assembly.Load("XF.DB.SqlServer");
Type type1 = assembly.GetType("XF.DB.SqlServer.Singleton");
Singleton singleton4 = (Singleton)Activator.CreateInstance(type1, true);
Singleton singleton5 = (Singleton)Activator.CreateInstance(type1, true);
Singleton singleton6 = (Singleton)Activator.CreateInstance(type1, true);
Console.WriteLine($"{object.ReferenceEquals(singleton4, singleton6)}");
1.4.2 反射创建泛型
Assembly assembly6 = Assembly.Load("XF.DB.SqlServer");
Type type2 = assembly.GetType("XF.DB.SqlServer.GenericClass`3");//`3为类型占位符,有几个类型就是几,这里有3个类型
Type typeMake = type2.MakeGenericType(new Type[] { typeof(string), typeof(int), typeof(DateTime) });//确定泛型的类型
object genericInstance = Activator.CreateInstance(typeMake);//在创建实例的时候,一定要明确具体的类型
GenericClass<string,int,DateTime> gc = genericInstance as GenericClass<string, int, DateTime>;
gc.Show("Olive", 116, DateTime.Now);
1.5 反射调用实例方法、静态方法、重载方法
1.5.1 反射调用实例方法
Assembly assembly6 = Assembly.Load("XF.DB.SqlServer");
Type type2 = assembly6.GetType("XF.DB.SqlServer.ReflectionTest");
object test = Activator.CreateInstance(type2);
MethodInfo method = type2.GetMethod("Show");//调用无参函数
method.Invoke(test, null);
MethodInfo method1 = type2.GetMethod("Show1");//调用有参函数
method1.Invoke(test,new object[] { "Olive" });
1.5.2 反射调用静态方法
Assembly assembly6 = Assembly.Load("XF.DB.SqlServer");
Type type2 = assembly6.GetType("XF.DB.SqlServer.ReflectionTest");
object test = Activator.CreateInstance(type2);
MethodInfo method6 = type2.GetMethod("Show4");//调用静态函数,实例可要
method6.Invoke(test, new object[] { "Olive" });
MethodInfo method7 = type2.GetMethod("Show4");//调用静态函数,实例为空
method7.Invoke(null, new object[] { "Olive" });
1.5.3 反射调用重载方法
Assembly assembly6 = Assembly.Load("XF.DB.SqlServer");
Type type2 = assembly6.GetType("XF.DB.SqlServer.ReflectionTest");
object test = Activator.CreateInstance(type2);
MethodInfo method2 = type2.GetMethod("Show2", new Type[] { });//调用重载函数,无参
method2.Invoke(test, null);
MethodInfo method3 = type2.GetMethod("Show2", new Type[] {typeof(int) });//调用重载函数
method3.Invoke(test, new object[] { 116 });
MethodInfo method4 = type2.GetMethod("Show2", new Type[] {typeof(string),typeof(int) });//调用重载函数
method4.Invoke(test, new object[] { "Olive",116 });
MethodInfo method5 = type2.GetMethod("Show2", new Type[] { typeof(int) ,typeof(string)});//调用重载函数
method5.Invoke(test, new object[] { 116,"Olive" });
1.6 调用私有方法 调用泛型方法
1.6.1 反射调用私有方法
Assembly assembly6 = Assembly.Load("XF.DB.SqlServer");
Type type2 = assembly6.GetType("XF.DB.SqlServer.ReflectionTest");
object test = Activator.CreateInstance(type2);
MethodInfo method8 = type2.GetMethod("Show3",BindingFlags.Instance|BindingFlags.NonPublic);//调用私有函数
method8.Invoke(test, new object[] { "Olive" });
1.6.2 反射调用泛型方法
Assembly assembly6 = Assembly.Load("XF.DB.SqlServer");
Type type2 = assembly6.GetType("XF.DB.SqlServer.GenericMethod");
object test = Activator.CreateInstance(type2);
MethodInfo method = type2.GetMethod("Show");//调用无参函数
var methodNew = method.MakeGenericMethod(new Type[] { typeof(string), typeof(int), typeof(DateTime) });
methodNew.Invoke(test,new object[] { "Olive", 116, DateTime.Now });
1.6.3 反射调用泛型类型+泛型方法
Type type2 = assembly6.GetType("XF.DB.SqlServer.GenericDouble`1");
Type type3 = type2.MakeGenericType(new Type[] { typeof(int) });
object test = Activator.CreateInstance(type3);
MethodInfo method = type3.GetMethod("Show");
var methodNew = method.MakeGenericMethod(new Type[] { typeof(string), typeof(DateTime) });
methodNew.Invoke(test, new object[] { 116, "Olive", DateTime.Now });
1.7 反射字段和属性,分别获取值和设置值
1.7.1 反射字段、获取、设置值
Assembly assembly6 = Assembly.Load("XF.Model");
Type type = assembly6.GetType("XF.Model.People");
object people = Activator.CreateInstance(type);
foreach(var field in type.GetFields())
{
Console.WriteLine($"{type.Name}.{field.Name}={field.GetValue(people)}");
if (field.Name.Equals("Description"))
field.SetValue(people, "Good boy");
}
1.7.2 反射属性、获取、设置值
Assembly assembly6 = Assembly.Load("XF.Model");
Type type = assembly6.GetType("XF.Model.People");
object people = Activator.CreateInstance(type);
foreach(var prop in type.GetProperties())
{
Console.WriteLine($"{type.Name}.{prop.Name}={prop.GetValue(people)}");
if (prop.Name.Equals("Id"))
prop.SetValue(people, 116);
}
1.8 反射的好处和局限
好处:动态
局限:使用麻烦
避开编译器检查
性能问题:正常情况下基本上不存在性能问题
.NET知识梳理——2.反射的更多相关文章
- [SQL] SQL 基础知识梳理(一)- 数据库与 SQL
SQL 基础知识梳理(一)- 数据库与 SQL [博主]反骨仔 [原文地址]http://www.cnblogs.com/liqingwen/p/5902856.html 目录 What's 数据库 ...
- [SQL] SQL 基础知识梳理(二) - 查询基础
SQL 基础知识梳理(二) - 查询基础 [博主]反骨仔 [原文]http://www.cnblogs.com/liqingwen/p/5904824.html 序 这是<SQL 基础知识梳理( ...
- [SQL] SQL 基础知识梳理(三) - 聚合和排序
SQL 基础知识梳理(三) - 聚合和排序 [博主]反骨仔 [原文]http://www.cnblogs.com/liqingwen/p/5926689.html 序 这是<SQL 基础知识梳理 ...
- [SQL] SQL 基础知识梳理(四) - 数据更新
SQL 基础知识梳理(四) - 数据更新 [博主]反骨仔 [原文]http://www.cnblogs.com/liqingwen/p/5929786.html 序 这是<SQL 基础知识梳理( ...
- [SQL] SQL 基础知识梳理(五) - 复杂查询
SQL 基础知识梳理(五) - 复杂查询 [博主]反骨仔 [原文]http://www.cnblogs.com/liqingwen/p/5939796.html 序 这是<SQL 基础知识梳理( ...
- solr DIH 知识梳理
solr DIH 知识梳理 web.xml中listener配置 <listener> <listener-class>org.apache.solr.handler.data ...
- Anliven - 基础知识梳理汇总 - 软件测试
基础知识梳理 - 软件测试 - 概念 基础知识梳理 - 软件测试 - 分类 基础知识梳理 - 软件测试 - 流程 基础知识梳理 - 软件测试 - 用例 基础知识梳理 - 软件测试 - 方法 基础知识梳 ...
- 图形学理论知识 BRDF 双向反射分布函数(Bidirectional Reflectance Distribution Function)
图形学理论知识 BRDF 双向反射分布函数 Bidirectional Reflectance Distribution Function BRDF理论 BRDF表示的是双向反射分布函数(Bidire ...
- [C# 基础知识梳理系列]专题六:泛型基础篇——为什么引入泛型
引言: 前面专题主要介绍了C#1中的2个核心特性——委托和事件,然而在C# 2.0中又引入一个很重要的特性,它就是泛型,大家在平常的操作中肯定会经常碰到并使用它,如果你对于它的一些相关特性还不是很了解 ...
随机推荐
- laravel框架api路由
Route::group(['namespace' => 'Api'], function (){ Route::any('send','SmsController@send'); }); gr ...
- 解决并发问题的CAS思想及原理
全称为:Compare and swap(比较与交换),用来解决多线程并发情况下使用锁造成性能开销的一种机制: 原理思想:CAS(V,A,B),V为内存地址,A为预期原值,B为新值.如果内存地 ...
- 牛客CSP-S提高组赛前集训营4 赛后总结
复读数组 分成 3 种区间算答案: 一个块内的区间 两个块交界处,长度小于块长的区间 长度不小于块长的区间 对于第三种区间,容易发现每个区间的权值一样,只需要算出个数即可. 对于前两种空间,我的思路是 ...
- BK: How to read a book 第四篇
第四篇 阅读的最终目标 第二十章 阅读的第四个层次:主题阅读 在做主题阅读时的要求: 1. 知道:知道应该读哪些书. 在面对如此庞大的相关资料时,我们要如何决定我们要研究的主题是什么呢. 如何判断属于 ...
- 我的python笔记06
面向对象学习 本节内容: 面向对象编程介绍 为什么要用面向对象进行开发? 面向对象的特性:封装.继承.多态 类.方法. 引子 你现在是一家游戏公司的开发人员,现在需要你开发一款叫做< ...
- 数据升级包 - bin文件
运行完升级包后,正常的现象 开头: 结尾:
- <软件工程基础>
我是JX_Z,学习信息安全方向 //(怎么在这头不头尾不尾的地方弄个自我介绍这么尴尬呢) 之前也写过一些随笔记录自己的学习过程 软件工程基础课程中遇到的问题和学习心得都会记录在这篇文章中不断更新. 谢 ...
- 初识消息队列--ActiveMq
消息队列 即MessageQueue,是一种消息中间件,在遇到系统请求量比较大的情况下,导致请求堆积过多无法及时返回,可以通过它进行异步的消息处理,从而缓解系统压力. ActiveMq ActiveM ...
- 清理 /dev/vda1 系统磁盘
df-h检查一台服务器磁盘使用空间,发现磁盘已经使用了100% 思路是: 1.cd /usr 2.du -sh * 看哪个目录占用空间大 3.重复前两步,根据实际情况删除或者移走 4.日志的话可以运行 ...
- Codeforces Round #600 (Div. 2) D。 Harmonious Graph
#include<iostream> using namespace std ; ; int p[N]; int cnt; int find(int x) { if(p[x]!=x) p[ ...