C#高级开发之反射(Reflection)二

C#编译运行原理 人类能识别的认识的C#高级语言 通过vs内置编译器编译 生成 dll或是exe(主要包含metadata+IL)然后dll或是exe 依赖 CLR/JIT 运行转变成 机器能识别的 机器码(010101)
经历两次编译过程把C#人类高级语言转变成机器码(010101)
1 反射定义:反射是.net框架提供帮助类库,通过反射,可以在运行时获取程序或程序集中的每一个类型(包括类,结构,委托,接口,枚举等)
的成员或是成员信息并使用(即可以获取并使用程序或程序集的matadata信息)。
 1.1反射中两大类Assembly+Type类
1)使用System.Reflection.Assembly类定义和加载程序集,加载在程序集清单中列出模块,以及从此程序集中查找类型并创建该类型的实例。
Assembly类可以获得程序集(DLL)的信息,也可以动态的加载程序集,以及在程序集中查找类型信息,并创建该类型的实例
Assembly assembly = Assembly.Load("DB.Oracle");//从当前目录加载dll(DB.Oracle即为项目类库名称)
Assembly assembly1 = Assembly.LoadFile(@"F:\StudyProject for TEST\MyReflection\DB.Oracle\bin\Debug\DB.Oracle.dll");//指定完整路径加载 可以是别的路径 本质还是指定到具体路径的Load方法
Assembly assembly2 = Assembly.LoadFrom("DB.Oracle.dll");//完整文件名称,需要带后缀 本质还是Load方法
通过Assembly获取程序集中类
Type[] t =assembly.GetTypes();//获取指定加载进来的dll中所有的类,
Type type = assembly.GetType("DB.Oracle.MyOracleHelper");//获取指定类的type信息,单独获取某个类的信息 通过该信息可以创建出对象
(2)使用System.Type 类可以访问任何给定数据类型的信息。 对于反射起着核心的作用,但它是一个抽象的基类,Type有与每种数据类型对应的派生类,我们使用这个派生类的对象的方法、字段、属性来查找有关该类型的所有信息。
获取给定类型的Type引用有3种常用方式
1.使用C# typof运算符准对的是某一个类型 Type type = typeof(string)
2.使用对象GetType()方法 准对的是某一个变量 string s = "test"; Type type = s.GetType();
3.使用Type类的静态方法GetTyep() Type type =Type.GetType("System.String");
4.Type类常用方法如下:
GetConstructor(), GetConstructors():返回ConstructorInfo类型,用于取得该类的构造函数的信息(ConstructorInfo[] constructorInfos = type.GetConstructors();//获取当前Type定义的所有公共构造函数) GetEvent(), GetEvents():返回EventInfo类型,用于取得该类的事件的信息(EventInfo[] eventInfos = type.GetEvents();//返回当前Type定义或继承的所有公共事件) GetField(), GetFields():返回FieldInfo类型,用于取得该类的字段(成员变量)的信息(FieldInfo[] fieldInfos = type.GetFields();//返回当前Type所有公共的字段)
GetMember(), GetMembers():返回MemberInfo类型,用于取得该类的所有成员的信息
GetMethod(), GetMethods():返回MethodInfo类型,用于取得该类的方法的信息(MethodInfo[] methodInfo = type.GetMethods();//返回当前Type的所有公共方法)
GetProperty(), GetProperties():返回PropertyInfo类型,用于取得该类的属性的信息(PropertyInfo[] propertyInfos = type.GetProperties();//返回当前Type所有公共属性);
2 反射主要用途(dll-IL-metadata-反射),主要是获取程序集或是DLL/exe的matadate信息并使用它(加载dll,读取module、类、属性、字段、方法、特性)
2.1利用反射机制中的Activator创建对象(IOC原理:Reflection+Factory+config)

工厂示例如下:
 1  private static string IDBHelpConfig = ConfigurationManager.AppSettings["IDBHelperConfig"];
 2         private static string DllName = IDBHelpConfig.Split(',')[0];
 3         private static string TypeName = IDBHelpConfig.Split(',')[1];
 4         public static IDBHelper CreateInstance()
 5         {
 6             Assembly assembly = Assembly.Load(DllName);//加载dll//Assembly.Load("DB.Oracle")
 7             Type type = assembly.GetType(TypeName);//获取指定类的type信息GetType("DB.Oracle.MyOracleHelper")
 8             object oDBHelper = Activator.CreateInstance(type);//创建对象
 9             IDBHelper iDBHelper = (IDBHelper)oDBHelper;//类型转换
10             return iDBHelper;
11           }
View Code

Assembly assembly = Assembly.Load("DB.SqlServer");
Type type = assembly.GetType("DB.SqlServer.Singleton");

Singleton singleton1 = (Singleton)Activator.CreateInstance(type, true);//反射创建对象调用私用的构造函数

object iDBHelper = Activator.CreateInstance(type, new object[] { "123" });//反射创建对象调用有参数构造函数

2.2利用反射机制获取类中的方法并调用方法(MVC路由原理url地址类名+方法名:Reflection+Method)典型的MVC路由原理通过找类中的方法找到对应的控制控制器和action

 Assembly assembly = Assembly.Load("DB.SqlServer");//加载dll

Type type = assembly.GetType("DB.SqlServer.MySqlServer");//获取获取指定类的type信息

MethodInfo methodInfo = type.GetMethod("show");//反射获取方法
methodInfo.Invoke(DBHelper, null);//反射调用无惨方法
MethodInfo methodInfo1 = type.GetMethod("show1");//反射获取方法
methodInfo1.Invoke(DBHelper, new object[] {123 });//反射调用有参数方法

MethodInfo methodInfo4 = type.GetMethod("show2");//反射获取方法
methodInfo4.Invoke(null,null);//反射调用静态无参方法

MethodInfo methodInfo6 = type.GetMethod("show4", BindingFlags.Instance |BindingFlags.NonPublic);//反射获取私有方法
methodInfo6.Invoke(DBHelper, new object[] {123 });//反射调用有参数方法

MethodInfo methodInfo5 = type.GetMethod("Query", new Type[] { typeof(int) });//反射获取重载有参数方法
methodInfo5.Invoke(DBHelper, new object[] {123 });//反射调用重载有参数方法

反射查找泛型类和泛型方法

Assembly assembly = Assembly.Load("DB.SqlServer");
Type typeG = assembly.GetType("DB.SqlServer.GenericTest`1");//反射获取泛型类的类型
Type NewTye = typeG.MakeGenericType(new Type[] { typeof(string) });//指定泛型类的类型
object CreateG = Activator.CreateInstance(NewTye);
MethodInfo methodInfo = NewTye.GetMethod("show");
MethodInfo newmethod=methodInfo.MakeGenericMethod(new Type[] { typeof(int), typeof(string) });//指定泛型类方法参数
newmethod.Invoke(CreateG, new object[] {123,"name" });//调用泛型方法

 2.3利用反射机制获取类中的属性字段并使用或设置值(ORM原理:Reflection+Property/Field)

       //取得ID字段 
        FieldInfo fi = t.GetField("ID");
        //给ID字段赋值 
        fi.SetValue(obj, "k001");
        //取得MyName属性 
        PropertyInfo pi1 = t.GetProperty("MyName");
        //给MyName属性赋值 
        pi1.SetValue(obj, "grayworm");

以下实例是需要两个类中的字段属性名字完全相同

 1 People people = new People();
 2                         people.Id = 123;
 3                         people.Name = "张三";
 4                         people.Description = "张四的哥哥";
 5                         Type otype = typeof(People);
 6                         Type DTOtype = typeof(PeopleDTO);
 7                         object dtoPeople = Activator.CreateInstance(DTOtype);
 8                         foreach (var dto in DTOtype.GetProperties())
 9                         {
10                             object value = otype.GetProperty(dto.Name).GetValue(people);//获取otype中dto.Name属性的值;
11                             dto.SetValue(dtoPeople, value);//给dtoPeople该实例中dto属性设置值;
12                             dto.SetValue(dtoPeople, otype.GetProperty(dto.Name).GetValue(people));//两者结合
13                         }
14                         foreach (var dto in DTOtype.GetFields())
15                         {
16                             object value = otype.GetField(dto.Name).GetValue(people);//获取otype中dto.Name字段的值;
17                             dto.SetValue(dtoPeople, value);//给dtoPeople该实例中dto字段设置值;
18                             dto.SetValue(dtoPeople, otype.GetField(dto.Name).GetValue(people));//两者结合
19                         }
View Code

总结 C#中反射机制用的相当频繁一些大型框架的原理都是基于反射 ,很需要深入了解原理,目前主流的框架MVC  ORM IOC等都是利用反射原理实现的

 

posted @ 2019-01-21 19:02  youzhangcai  阅读(999)  评论(0编辑  收藏  举报