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.反射的更多相关文章

  1. [SQL] SQL 基础知识梳理(一)- 数据库与 SQL

    SQL 基础知识梳理(一)- 数据库与 SQL [博主]反骨仔 [原文地址]http://www.cnblogs.com/liqingwen/p/5902856.html 目录 What's 数据库 ...

  2. [SQL] SQL 基础知识梳理(二) - 查询基础

    SQL 基础知识梳理(二) - 查询基础 [博主]反骨仔 [原文]http://www.cnblogs.com/liqingwen/p/5904824.html 序 这是<SQL 基础知识梳理( ...

  3. [SQL] SQL 基础知识梳理(三) - 聚合和排序

    SQL 基础知识梳理(三) - 聚合和排序 [博主]反骨仔 [原文]http://www.cnblogs.com/liqingwen/p/5926689.html 序 这是<SQL 基础知识梳理 ...

  4. [SQL] SQL 基础知识梳理(四) - 数据更新

    SQL 基础知识梳理(四) - 数据更新 [博主]反骨仔 [原文]http://www.cnblogs.com/liqingwen/p/5929786.html 序 这是<SQL 基础知识梳理( ...

  5. [SQL] SQL 基础知识梳理(五) - 复杂查询

    SQL 基础知识梳理(五) - 复杂查询 [博主]反骨仔 [原文]http://www.cnblogs.com/liqingwen/p/5939796.html 序 这是<SQL 基础知识梳理( ...

  6. solr DIH 知识梳理

    solr DIH 知识梳理 web.xml中listener配置 <listener> <listener-class>org.apache.solr.handler.data ...

  7. Anliven - 基础知识梳理汇总 - 软件测试

    基础知识梳理 - 软件测试 - 概念 基础知识梳理 - 软件测试 - 分类 基础知识梳理 - 软件测试 - 流程 基础知识梳理 - 软件测试 - 用例 基础知识梳理 - 软件测试 - 方法 基础知识梳 ...

  8. 图形学理论知识 BRDF 双向反射分布函数(Bidirectional Reflectance Distribution Function)

    图形学理论知识 BRDF 双向反射分布函数 Bidirectional Reflectance Distribution Function BRDF理论 BRDF表示的是双向反射分布函数(Bidire ...

  9. [C# 基础知识梳理系列]专题六:泛型基础篇——为什么引入泛型

    引言: 前面专题主要介绍了C#1中的2个核心特性——委托和事件,然而在C# 2.0中又引入一个很重要的特性,它就是泛型,大家在平常的操作中肯定会经常碰到并使用它,如果你对于它的一些相关特性还不是很了解 ...

随机推荐

  1. JAVA并发同步互斥实现方式总结

    大家都知道加锁是用来在并发情况防止同一个资源被多方抢占的有效手段,加锁其实就是同步互斥(或称独占)也行,即:同一时间不论有多少并发请求,只有一个能处理,其余要么排队等待,要么放弃执行.关于锁的实现网上 ...

  2. ECMAScript基本语法——⑤运算符 逻辑运算符

    &&与,会短路:左边为false右边就不参与运算||或,会短路:左边为true右边就不参与运算!非, 注意:在JavaScript中,如果运算数不是运算符要求的类型,那么JavaScr ...

  3. kanbanflow的使用

    也许在工作中大家都听说过番茄工作法,就是每次在一个番茄钟25分钟内保持高度专注,并且在时间结束的时候会提醒你,然后稍作休息5分钟:此外,在产品迭代开发过程中常常会接受到不同的task:那么,我们是否可 ...

  4. 安装SQL Server2008出现Restart computer failed的解决办法

    1.打开注册表编辑器 2.找到HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Session Manager双击文件夹 3.找到PendingF ...

  5. 其他 - PotPlayer - 基础快捷键总结

    概述 尝试使用 potplayer 的快捷键 背景 最近需要反复看录像 回看 慢速 其他各种 没错, 我的需求就是 游戏复盘... 环境 os win10.1903 player potplayer. ...

  6. CSS常用小技巧

    1.隐藏overflow滚动条 ::-webkit-scrollbar { display:none } 2.单行文字两端对齐(例:输入框前的label) // 若考虑兼容,文字间要有空格 { tex ...

  7. 修复ThinkPHP导出excel数字过大时显示为科学记数法

    修复ThinkPHP导出excel数字过大时显示为科学记数法,这种显示对于查看的用户来说是及其不友好的.所以,我们要使其转化为正常的数字串! 我在google 的过程中,查了一些资料.其中 1).// ...

  8. blob - 二进制文件流下载

    /** * 返回值文件类型为 blob 二进制流文件 * responseType: 'blob' * params 接口所需参数 * 命名文件名:依据时间戳命名文件名 * (导出时需要延迟,否则导出 ...

  9. setUserData

    node.setUserData();//设置每个节点的datanode.getUserData();

  10. 巨杉Tech | 使用 SequoiaDB + Docker + Nodejs 搭建 Web 服务器

    容器化技术的出现大大简化了应用开发人员在构建底层基础设施的工作.SequoiaDB 巨杉数据库于3.2.1版本正式推出了 Docker 容器化部署方案,本文将会基于 SequoiaDB 巨杉数据库与N ...