反射
反射是无处不在的,MVC、AOP、IOC、ORM、Attribute等等
- dll-IL-metadata-反射
- 反射加载dll,读取module、类、方法
- 反射创建对象,反射+简单工厂+配置文件
- 反射破坏单例,反射创建泛型
反射是程序员的快乐
解耦:去掉对细节的依赖
首先分析这张图
相关名词:
ILSpy
反编译工具,可以将DLL/EXE反编译到IL或C#
IL
中间语言
标准的面向对象语言,但是不太好阅读。
metadata
元数据
数据清单,只是描述了类中有什么
反射
Reflection
二次编译:
为了一次编译,不同平台使用;加一层中间层,更灵活。
反射的简单使用
-
动态加载
Assembly assembly = Assembly.Load("Ruanmou.DB.SqlServer");
-
获取类型
Type type = assembly.GetType("Ruanmou.DB.SqlServer.SqlServerHelper");
-
创建对象
object oDbHelper = Activator.CreateInstance(type);
-
类型转换
IDBHelper iDBHelper= oDbHelper as IDbHelper;
-
调用方法
iDBHelper.Query();
反射创建对象
普通类
无参数
没有跟参数,默认调用的就是无参数的构造函数
Activator.CreateInstance(type)
有参数
使用有参数的构造函数创建对象时,要指明参数
Activator.CreateInstance(type,new object[]{typeof(paramater1),typeof(paramater2),...})
注意:给的参数类型不一样的时候,自动匹配去调用哪个构造函数进行创建对象
泛型类
首先需要明确的是,泛型在中间语言中会解析成`1,`2,`3这样用来表示带有几个泛型参数。因此,在反射获取类型时,需要用assembly.GetType("泛型的类名`泛型参数个数")的形式
下方所示代码,对象type是泛型类的类型信息,对象type1是泛型类指定了参数后的实际类的类型信息。调用时应使用type1.
Assembly assembly3 = Assembly.LoadFrom("Zhaoxi.AspNetCore.DB.SqlServer.dll");
Type type = assembly3.GetType("Zhaoxi.AspNetCore.DB.SqlServer.GenericClass`3");
Type type1 = type.MakeGenericType(new Type[] { typeof(int), typeof(string), typeof(DateTime) });
反射调用方法
普通方式调用方法时,先构造对象,然后得到实例,调用实例方法。
在反射中,需要有实例,才能调用到方法
使用方法:
Assembly assembly = Assembly.LoadFrom("MyAssembly.dll");
Type type = assembly.GetType("MyAssembly.MyClass");
object objIns = Activator.CreateInstance(type);
MethodInfo showInfo=type.GetMethod("MyMethod");
showInfo.Invoke(objIns,new object[0]);
普通方法(无参数)
type.GetMethod("MyMethod")
普通方法(有参数)
type.GetMethod("MyMethod",new type[]{typeof(参数类型)})
重载方法
根据参数个数、类型区别使用哪个
type.GetMethod("MyMethod", new Type[] { typeof(参数1类型), typeof(参数2类型),... })
私有方法
在调用时给定参数BindingFlags(enum)的取值 NonPublic、Instance
type.GetMethod("MyMethod", BindingFlags.NonPublic | BindingFlags.Instance)
静态方法
在调用时给定参数BindingFlags(enum)的取值 Static、public
type.GetMethod("MyMethod", BindingFlags.Static | BindingFlags.Public)
泛型方法
在调用时得到的第一个MethodInfo是泛型方法,还需要使用MakeGenericMethod方法创建“实例方法”,然后使用实例方法的Invoke进行调用。
MethodInfo show = type1.GetMethod("Show");
MethodInfo show1 = show.MakeGenericMethod(new Type[] { typeof(string), typeof(DateTime) });
show1.Invoke(obj, new object[] { 456, "cxx", DateTime.Now });
如果是泛型类的泛型方法,且其中的泛型参数一致,则可以不用MakeGenericMethod方法创建“实例方法”,直接使用这个方法(因为参数已经确认)。
即如果泛型参数没有确认,就必须使用MakeGenericType、MakeGenericMethod确认泛型参数,得到实际的类或方法。
反射在框架中的应用
IOC框架:反射+配置文件+简单工厂 == IOC框架中的应用
MVC:Controller/Action -> /Home/Index?id=123
MVC中调用方法就是反射的真实写照
ORM应用:
对象关系模型,就是通过对类的操作达成对数据库的操作
方法、属性、字段
封装ORM数据库访问
创建和数据库中表相对应的类
类中的属性和表中的字段一一对应
使用反射对ADO.NET中的SQL语句进行拼装
循环得到属性的名称、值
使用静态拼接好的SQL语句进行读取、增删改查数据库的操作
以上就是使用反射的ORM封装