C# 反射(Reflection)
首先说一下反射的优点:动态!!!
首先了解一下C#编译运行过程,大致如下所示:
首先被编译器编译成dll/exe,一般我们发布的都是这个东西,然后在运行的时候会被CLR/JIT编译成机器码。
为什么不直接通过编译器编译成机器码呢?答案就是:通过CLR/JIT可以根据不同的平台编译成不同的机器码,用以一次编译多平台运行。
而我们通过反射处理的就是matadata这一块,里面包含了我们写的类文件,方法等等。
微软提供的反射工具主要是 System.Reflection。
反射的使用
- 第一步:加载dll文件
// 第一种:直接写dll文件名,不用加后缀
Assembly assembly = Assembly.Load("DB.MySql1");
// 第二种:使用完整路径加载。(可以是别的目录,不推荐使用,虽然不会错,但是如果没有对应的依赖项,使用会报错)
Assembly assembly1 = Assembly.LoadFile(@"E:\学习\.net learn\Net_Learn\DB.MySql1\bin\Debug\DB.MySql1.dll");
// 第三种:使用类库名带后缀,或者直接路径
Assembly assembly2 = Assembly.LoadFrom("DB.MySql1.dll");
通过上述的加载需要单设的文件后,我们可以获取部分信息:
// GetModules()获取模块信息
foreach (var item in assembly.GetModules())
{
Console.WriteLine("获取模块信息:" + item.FullyQualifiedName);
}
// GetTypes()获取类型信息
foreach (var item in assembly.GetTypes())
{
Console.WriteLine("获取类型信息:" + item.FullName);
}
- 获取类型信息
// 这里的 DB.MySql1.MySqlHelper 是 类库名.类名
Type type = assembly.GetType("DB.MySql1.MySqlHelper");
- 创建对象
// 创建对象:Activator.CreateInstance(type),与 new MySqlHelper() 效果一样
object oDBHelper = Activator.CreateInstance(type);
// 一般到了这里,我们觉得就可以直接像 new MySqlHelper() 之后一样去调用方法了
// oHelper 是object,不能调用,但实际方法是有的,编译器不认可
// oHelper.Query();
4 类型转换
// 所以这里需要做类型转换
IDBHelper iDBHelper = (IDBHelper)oDBHelper;
5 方法调用
iDBHelper.Query();
上述操作如果按照直接实例化的方式:
IDBHelper dBHelper = new MySqlHelper();
dBHelper.Query();
相比之下反射的操作比直接实例化要复杂一些。
为了避免每次写一堆代码,我们也可以写一个公共方法:
/// <summary>
/// 使用工厂类封装反射方法
/// <para>更改配置文件就可以执行不同的操作,无需编译文件</para>
/// </summary>
public class Factory
{
// 读取配置文件中配置的 类库名加类名
private static string IDBHelperConfig = ConfigurationManager.AppSettings["IDBHelperConfig"];
// 类库名
private static string DllName = IDBHelperConfig.Split(',')[1];
// 类名
private static string TypeName = IDBHelperConfig.Split(',')[0];
public static IDBHelper CreateHelper()
{
//1 加载dll
Assembly assembly = Assembly