一.何谓反射

反射:是.net framework提供的一个访问metadata的帮助类库,可以获取信息并且使用
动态是反射中的最大优点。

二:反射如何使用

#region 反射的加载方式
获取当前路径下面的dl或者exe,不带后缀(MyReflection.exe 是编译后生成的exe执行文件),从Exe所在的路径进行查找
Assembly assembly = Assembly.Load(@"MyReflection");
//获取完整路径下面的dl或者exe,要加后缀
Assembly assemblyFrom = Assembly.LoadFrom(@"D:\MyReflection\bin\Debug\MyReflection.exe");
//获取完整路径下面的dl或者exe,要加后缀
Assembly assemblyFile = Assembly.LoadFile(@"D:\MyReflection\bin\Debug\MyReflection.exe");
foreach (var item in assembly.GetModules())
{//Modules当前的exe或者dll的名字(MyReflection.exe)Console.WriteLine(item.Name);
}
//当前所包含的实体类(IDBHelper,SqlServerHelper,Program)
foreach (var item in assembly.GetTypes())
{foreach(var method in item.GetMethods()){Console.WriteLine(method.Name);      }Console.WriteLine(item.Name);
}foreach (var item in assembly.GetCustomAttributes())
{Console.WriteLine(item.ToString());
}
//获取到有多个构造函数
foreach (var ctor in type.GetConstructors())
{
Console.WriteLine(ctor.GetParameters());
//获取构造函数里面的参数
foreach (var item in ctor.GetParameters())
{
Console.WriteLine(item.ParameterType);
}
}
#endregion

三.反射的应用

(一)可以利用反射 创建一个类的实例,并调用他的方法

1.创建步骤

例如:

(1).获取类型:
Type dbhelperType = assembly.GetTyp(“Ruanmou.DB.MySql.MySqlHelper”);//== 获取所需创建类型的类型信息,传参数必须传递完整类名,从命名空间开始==
(2).创建类型对应的实例对象
//用Activator.CreateInstance(类型参数)创建所需类型的实例对象
object oDBHelper = Activator.CreateInstance(dbhelperType);
(3).转换并调用方法:
用其对应的接口进行转换
IDBHelper idbhelper = oDBHelper as IDBHelper;
idbhelper.Query();

2.具体应用

在写程序的时候,需要灵活运用类的时候,可以先在配置文件中,将需要的类型配置进去,然后在程序中根据配置文件灵活的创建所需要的类型对象:举例,程序有可能需要多种数据库,MySql 和SqlServer,写底层数据库连接的时候并不知道上层需要哪个,于是可以利用在配置文件中的连接字符串中配置Provider的dll,用反射的方式在底层创建连接字符串的时候,根据上层传入的连接字符串来灵活创建底层连接Connection.

/// <summary>
/// 反射得到一个对象/// </summary>public class SimpleFactory{//读取配置文件AppSetting里面的key// <appSettings>// <add key = "DbConfig" value="MyReflection,MyReflection.MySqlServerHelper"/>//</appSettings>private static string ConfigStr = ConfigurationManager.AppSettings["DbConfig"];private static string DllName = ConfigStr.Split(',')[0];  //命名空间private static string TypeName = ConfigStr.Split(',')[1]; //类型要完整命名空间+类名public static T CreateInstance<T>(){Assembly assembly = Assembly.Load(DllName);Type type = assembly.GetType(TypeName);var objectInstance = Activator.CreateInstance(type);return (T)objectInstance; //要强制转换一下,因为牵涉到编译性语言和运行时语言}}

(二):反射调用多构造函数,调用私有构造函数(破坏单例),调用泛型类

首先创建一个实体类,包含有参无参构造函数,然后有参无参的方法,如下:

/// <summary>/// sqlServer/// </summary>public class SqlServerHelper : IDBHelper{//private SqlServerHelper()//{//    Console.WriteLine("私有构造函数");//}//无参构造函数public SqlServerHelper(){Console.WriteLine("公有无参构造函数");}//传入一个int型参数的构造函数public SqlServerHelper(int iParam){Console.WriteLine($"int的构造函数--{iParam}");}//传入一个string型参数的构造函数public SqlServerHelper(string sParam){Console.WriteLine($"string的构造函数--{sParam}");}//传入两个参数的构造函数public SqlServerHelper(int iParam, string sParam){Console.WriteLine($"int和string的构造函数--int={iParam} ;string={sParam}");}//类内部的无参方法public void Show(){Console.WriteLine("Show");}//类内部的Show1的无参方法public void Show1(){Console.WriteLine("Show1的无参方法");}//类内部的Show1的int重载方法public void Show1(int iParam){Console.WriteLine($"Show1的int重载--{iParam}");}//类内部的Show1的两参重载方法public void Show1(int iParam, string sParam){Console.WriteLine($"Show1两参数 iparam={iParam};sParam={sParam}");}
}

1.调用上面例子类中的 有参 或者 无参构造函数

Assembly assembly = Assembly.Load("MyReflection"); //获取当前路径下面的dl或者exe,不带后缀
Type dbHelperType = assembly.GetType("MyReflection.SqlServerHelper"); //传完整名称获类型(命名空间+类名)
//调用多个构造函数(有参,无参)
var obSqlServerHelper = Activator.CreateInstance(dbHelperType); //无参的构造函数
Activator.CreateInstance(dbHelperType, new object[] { 11 }); //int的构造函数
Activator.CreateInstance(dbHelperType, new object[] { "testbywss" }); //调用string的构造函数
Activator.CreateInstance(dbHelperType, new object[] { 123, "testbywss" }); //调用string的构造函数

2. 调用类的私有构造函数

//私有构造函数Type singletonType = assembly.GetType("MyReflection.Singleton"); //传入完整名称获取类型(命名空间+类名)var object1 = Activator.CreateInstance(singletonType, true); //设置成true能调用私有/公布的构造函数,如果不设置则只能调用公有构造函数

3.不必强制类型转换,调用 普通方法,静态方法,重载方法:

在利用了反射实例化对象之后,可以不需要强制类型转换,直接调用其方法

Type dbhelperType = assembly.GetTyp(“Ruanmou.DB.SqlServer.SqlServerHelper ”);
object obSqlServerHelper = Activator.CreateInstance(dbhelperType);

(1)普通方法

Type 类型 的对象,有一个方法 GetMethods方法,可以获取这个类型对象中所指定的方法,
如下:
MethodInfo methodInfo = dbhelperType.GetMethod(“Show”); //MethodInfo 类,用于描述方法
用获取到指定方法的 MethodInfo 对象 来调用方法
methodInfo.Invoke(obSqlServerHelper, null); //第一个参数:要调用方法的实例,普通方法必须实例化之后进行调用,上面已经用Activator.CreateInstance实例化了一个该Type的实例,这里将其传入,第二个参数:是方法需要的参数,如果没有则设置为null

(2) 静态方法调用

MethodInfo staticMethodInfo = dbHelperType.GetMethod(“Show5”); //调用单个普通的实例方法
== staticMethodInfo.Invoke(null, new object[] { “静态方法第一种调用方式” }); //第一个参数:是应用对象,如果是静态可以不用写;第二个参数:是方法需要的参数,如果没有则设置为null ==
staticMethodInfo.Invoke(obSqlServerHelper, new object[] { “静态方法第二种调用方式” });//重载方法调用

(3) 调用重载方法

重载方法
MethodInfo method2 = dbHelperType.GetMethod(“Show1”, new Type[] { }); //调用无参的函数
method2.Invoke(obSqlServerHelper, null);

MethodInfo method3 = dbHelperType.GetMethod(“Show1”, new Type[] { typeof(int) }); //int参数的方法
method3.Invoke(obSqlServerHelper, new object[] { 11 });

MethodInfo method4 = dbHelperType.GetMethod(“Show1”, new Type[] { typeof(int), typeof(string) }); //调用2个参数的方法,new Type[] { typeof(int), typeof(string) } 顺序一定要跟调用的方法的参数顺序保持一致
method4.Invoke(obSqlServerHelper, new object[] { 1111, “ddd” });

4:调用泛型

(1)首先要创建一个实体类如下:
#region 泛型类public class GenericClass<T, W, F>{public void Show(T t, W w, F f){Console.WriteLine($"t.type={t.GetType().Name};}");}}public class GenericMethod{public void Show<T, W, X>(T t, W w, X x){Console.WriteLine($"t.type={t.GetType().Name};");}}public class GenericDouble<T>{public void Show<W, X>(T t, W w, X x){Console.WriteLine($"t.type={t.GetType().Name};");}}#endregion
(2)调用泛型方法如下

//创建泛型
Assembly assembly = Assembly.Load(“MyReflection”); //获取当前路径下面的dl或者exe,不带后缀
== 创建泛型类,创建泛型类的时候,除了写好类名,还要给占位符,以告诉系统这个类是一个泛型类,3个占位符,表示泛型类传入三个类型参数。==
Type genericType = assembly.GetType("MyReflection.GenericClass3"); //3是泛型类需要的参数
== 在调用实例化之前,要先指定具体的泛型的类型==
Type typeGenericNew = genericType.MakeGenericType(typeof(int), typeof(int), typeof(int)); //需要指定泛型类的类型
GenericClass<int, int, int> oGeneric = (GenericClass<int, int, int>)Activator.CreateInstance(typeGenericNew);
oGeneric.Show(1, 30, 60);

Type genericType1 = assembly.GetType(“MyReflection.GenericMethod”); //普通的类
var genericMethod = Activator.CreateInstance(genericType1) as GenericMethod;
genericMethod.Show<int, string, double>(1, “1”, 2);

5:调用私有方法

//私有方法
//调用私有方法,有参数
MethodInfo method5 = dbHelperType.GetMethod("Show5", BindingFlags.NonPublic | BindingFlags.Instance);
method5.Invoke(obSqlServerHelper, new object[] { 5.0 });//私有方法,无参数
MethodInfo method6 = dbHelperType.GetMethod("Show6", BindingFlags.NonPublic | BindingFlags.Instance);
method6.Invoke(obSqlServerHelper, null);

6:调用普通方法的泛型方法

//类的泛型方法调用
Type genericMethodType = assembly.GetType("MyReflection.GenericMethod");
var objectGeneric = Activator.CreateInstance(genericMethodType);
MethodInfo genericMethod = genericMethodType.GetMethod("Show");
//这一步是调用泛型方法的关键,给泛型方法的参数类型指定具体类型,并告诉系统这是一个泛型方法
MethodInfo genericMethodNew = genericMethod.MakeGenericMethod(typeof(int), typeof(int));

//对泛型方法进行调用,传入的第一个参数是调用哪个实例的这个泛型方法,第二个参数是传入参数
genericMethodNew.Invoke(objectGeneric, new object[] { 1, 4 });

.NET 反射原理及其运用相关推荐

  1. java反射原理三种,Java反射的原理,作用

    什么是反射,反射原理 java类的执行需要经历以下过程 编译:.java文件编译后生成.class字节码文件 加载:类加载器负责根据一个类的全限定名来读取此类的二进制字节流到JVM内部,并存储在运行时 ...

  2. 【Android架构师java原理详解】二;反射原理及动态代理模式

    前言: 本篇为Android架构师java原理专题二:反射原理及动态代理模式 大公司面试都要求我们有扎实的Java语言基础.而很多Android开发朋友这一块并不是很熟练,甚至半路初级底子很薄,这给我 ...

  3. 假笨说-从一起GC血案谈到反射原理

    概述 公司之前有个大内存系统(70G以上)一直使用CMS GC,不过因为该系统对时间很敏感,偶尔会因为gclocker导致remark特别长(虽然加了-XX:+CMSScavReengeBeforeR ...

  4. java 反射获取属性名和值_面试官这样问我Java反射原理,我刚好都会

    上周我投递出了简历,岗位是java后端开发工程师.这周美团面试官给我进行了面试,面试过程中他问了Java的反射原理.(不得不夸一句,美团的效率真高,上午面完一面,晚上二面马上安排上了.) 无论什么Ja ...

  5. java基础之 反射_Java基础之反射原理与用法详解

    本文实例讲述了Java基础之反射原理与用法.分享给大家供大家参考,具体如下: 1.什么是反射? 反射其实就是动态的加载类,我们在写JDBC的时候加载驱动Class.forName("xxx& ...

  6. 【信号完整性】信号反射原理

    信号反射原理 0 前言 1 参考方向 2 行波的折射与反射 3 几种特殊端接情况分析 0 前言 一般情况下,可以使用行波的概念去分析信号在传输线中的传输过程.线路中均匀性开始遭到破坏的点称为节点,当行 ...

  7. 卡特兰数 默慈金数 默慈金三角形 反射原理

    卡特兰数 公式 递推式: f ( n ) = ∑ f ( i ) ∗ f ( n − i − 1 ) f(n) = ∑f(i) * f(n-i-1) f(n)=∑f(i)∗f(n−i−1) 0 ≤ i ...

  8. 面试官这样问我Java反射原理,我刚好都会

    上周我投递出了简历,岗位是java后端开发工程师.这周美团面试官给我进行了面试,面试过程中他问了Java的反射原理.(不得不夸一句,美团的效率真高,上午面完一面,晚上二面马上安排上了.) 无论什么Ja ...

  9. Java对象的打印_java反射原理制作对象打印工具

    主要运用java反射原理,格式化输出java对象属性值,特别是list 和map. MyTestUtil.java package utils; import java.lang.reflect.Fi ...

  10. ULua反射原理——自我理解,有问题请斧正,谢谢!

    ULua反射原理 旧版本ULua 使用的类 实现方式 现版本的ulua(tolua) 实现方式 wrap:What ,How? What:wrap是什么 How :Wrap使用与生成 How :对于庞 ...

最新文章

  1. Silverlight 5的时间表及大量问题
  2. 自己整理的shell笔记
  3. mysql 从第二行开始_Mysql主备一致性问题
  4. 未能加载程序集或它的一个依赖项_英伟达发布kaolin:一个用于加速3D深度学习研究的PyTorch库...
  5. php如何向数组增加数据,php向数组中增加数据的方法是什么
  6. hive mysql编码问题_Hive中文乱码 生产环境问题解决
  7. 团队任务3:第一次冲刺
  8. ICBU可控文本生成技术详解
  9. datax 导入数据中文乱码_DataX在有赞大数据平台的实践
  10. html5中框架怎么写,html框架布局模板
  11. 【BurpSuite学习篇】四:Scanner 漏洞扫描模块
  12. 【BX学习之打印机】 惠普5055(无线WiFi小型打印机双面复印扫描一体机)
  13. Strut2的工作流程
  14. 笔记本Ubuntu系统,关上盖子不休眠设置
  15. linux报cpu软锁,内核软死锁
  16. 史玉柱正式退休:把互联网留给年轻人
  17. 支付宝周期扣款(支付后签约)业务功能总结(php+golang)
  18. centos系统mysql数据库搭建教程
  19. 经典四大排序(动图实现)
  20. 家族关系查询系统程序设计算法思路_数据结构课程设计(家族关系查询系统).....

热门文章

  1. 介绍 Golang 日志处理
  2. 数智十年,向新而行:2022 第十届CCF大数据与计算智能大赛在京启动
  3. 全国计算机等级考试可以一级二级一起考吗,全国计算机等级考试(一级到四级)全攻略...
  4. 多线程下载文件实践之旅
  5. Oem7F7 Win7激活 比SK PATCH/Loader更好更安全的激活 Nt6通用完美激活
  6. MySQL系列(四)
  7. 消防应急照明和疏散指示系统在某康养中心项目的应用
  8. ShellCode —— 入门
  9. shell银行账户管理程序_如何在德国设立银行账户?德国银行卡比较和解析
  10. 利用Python自动操纵鼠标键盘刷金币,工作室都是靠这种搬砖