博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
第六节:反射(几种写法、好处和弊端、利用反射实现IOC)
阅读量:6233 次
发布时间:2019-06-21

本文共 18993 字,大约阅读时间需要 63 分钟。

一. 加载dll,读取相关信息

1. 加载程序集的三种方式

 调用Assembly类下的三个方法:Load、LoadFile、LoadFrom。

1        //1.1 Load方法:动态默认加载当前路径下的(bin)下的dll文件,不需要后缀2             Assembly assembly = Assembly.Load("DB.SQLServer");3             //1.2 LoadFile方法:程序集的绝对路径4             Assembly assembly2 = Assembly.LoadFile(@"D:\我的框架之路\DotNet体系\02-DotNet进阶\02-反射\01-code\Reflection\bin\Debug\DB.SQLServer.dll");5             //1.3 LoadFrom方法:可以是当前路径(需要写上后缀.dll),也可以是绝对路径6             Assembly assembly3 = Assembly.LoadFrom("DB.SQLServer.dll");

2. 获取程序集中所有的类

 通过方法GetTypes来实现。

1 Assembly assembly = Assembly.Load("DB.SQLServer");2 Type[] t1 = assembly.GetTypes();

    通过方法GetType("类名全写")来实现获取单个类(DBHelper)。

1 Type tItem = assembly.GetType("DB.SQLServer.DBHelper");

3. 获取类中的所有构造函数

  通过方法GetConstructors来实现。

1 //1.加载程序集2 Assembly assembly = Assembly.Load("DB.SQLServer");3 //2.获取程序集中的特定类4 Type tItem = assembly.GetType("DB.SQLServer.DBHelper");5 //3.获取特定类中的所有构造函数6 ConstructorInfo[] cInfor = tItem.GetConstructors();

4. 获取类中的所有属性

  通过方法GetProperties来实现。

1  //1.加载程序集2 Assembly assembly = Assembly.Load("DB.SQLServer");3 //2.获取程序集中的特定类4 Type tItem = assembly.GetType("DB.SQLServer.DBHelper");5 //3.获取特定类中的所有属性6 PropertyInfo[] propertyInfo = tItem.GetProperties();

5. 获取类中的所有方法

   通过方法GetMethods来实现。

//1.加载程序集Assembly assembly = Assembly.Load("DB.SQLServer");//2.获取程序集中的特定类Type tItem = assembly.GetType("DB.SQLServer.DBHelper");//3.获取特定类中的所有方法MethodInfo[] methordInfo = tItem.GetMethods();

6. 获取类中的所有接口

  通过方法GetInterfaces来实现。

1 //1.加载程序集2 Assembly assembly = Assembly.Load("DB.SQLServer");3 //2.获取程序集中的特定类4 Type tItem = assembly.GetType("DB.SQLServer.DBHelper");5 //3.获取特定类中的所有接口6 Type[] type = tItem.GetInterfaces();

二. 反射创建对象

1. 反射创建对象

 通过Activator.CreateInstance()方法来创建对象

1.1 ReflectionTest类的代码

1  public class ReflectionTest 2     { 3         public int Id { get; set; } 4         public string Name { get; set; } 5  6         public string Field = null; 7         public static string FieldStatic = null; 8  9 10         #region 构造函数11         public ReflectionTest()12         {13             Console.WriteLine("这里是{0}无参数构造函数", this.GetType());14         }15 16         public ReflectionTest(string name)17         {18             Console.WriteLine("这里是{0} 有1个参数构造函数", this.GetType());19         }20 21         public ReflectionTest(int id, string name)22         {23             Console.WriteLine("这里是{0} 有2个参数构造函数", this.GetType());24         }25         #endregion26 27         public void Show1()28         {29             Console.WriteLine("这里是{0}的Show1", this.GetType());30         }31 32         public void Show2(int id)33         {34 35             Console.WriteLine("这里是{0}的Show2", this.GetType());36         }37 38         public static void ShowStatic(string name)39         {40             Console.WriteLine("这里是{0}的ShowStatic", typeof(ReflectionTest));41         }42 43         public void Show3()44         {45             Console.WriteLine("这里是{0}的Show3_1", this.GetType());46         }47 48         public void Show3(int id, string name)49         {50             Console.WriteLine("这里是{0}的Show3", this.GetType());51         }52 53         public void Show3(string name, int id)54         {55             Console.WriteLine("这里是{0}的Show3_2", this.GetType());56         }57 58         public void Show3(int id)59         {60 61             Console.WriteLine("这里是{0}的Show3_3", this.GetType());62         }63 64         public void Show3(string name)65         {66 67             Console.WriteLine("这里是{0}的Show3_4", this.GetType());68         }69 70         private void Show4(string name)71         {72             Console.WriteLine("这里是{0}的Show4", this.GetType());73         }74         public void ShowGeneric
(T name)75 {76 Console.WriteLine("这里是{0}的ShowStatic T={1}", this.GetType(), typeof(T));77 }78 }

1.2 反射创建对象的代码

1 //1.加载程序集 2 Assembly assembly = Assembly.Load("DB.SQLServer"); 3 //2.获取程序集中的特定类 4 Type tItem = assembly.GetType("DB.SQLServer.ReflectionTest"); 5  //3.1 无参构造函数 6 Activator.CreateInstance(tItem); 7  //3.2 一个参数的构造函数 8 Activator.CreateInstance(tItem ,"1"); 9 //3.3 两个参数的构造函数10  Activator.CreateInstance(tItem , 1,"2");

2. 反射破坏单例,调用私有构造函数

   单例代码

1  public sealed class Singleton 2     { 3         private Singleton() 4         { 5             Console.WriteLine("初始化一次"); 6         } 7  8         private static Singleton Instance = new Singleton(); 9 10         public static Singleton CreateInstance()11         {12             return Instance;13         }14     }

   破坏单例,调用私有构造函数代码

1 //1.加载程序集2 Assembly assembly = Assembly.Load("DB.SQLServer");3 //2. 获取单例类4 Type tc3 = assembly .GetType("DB.SQLServer.Singleton");5 //3. 创建对象6 Activator.CreateInstance(tc3, true);

3. 反射创建泛型(扩展)

1  //1.加载程序集2 Assembly assembly = Assembly.Load("DB.SQLServer");3  //2. 获取单例类4 Type tc4 = assembly4.GetType("DB.SQLServer.GenericClass`1");5 tc4 = tc4.MakeGenericType(typeof(int));6 Activator.CreateInstance(tc4);

三. IOC(反射+简单工厂+配置文件)

   背景:有三套相同的数据库,分别是SQLServer、MySQL、Oracle数据库,要求可以分别连接这三个不同的数据库,并且发布后,可以在不重新发布的情况下,切换连接数据库。

   对应上述背景,建立相应的解决方案,目录如下,并介绍介绍几种传统的解决方案

方案一:在Reflection中直接添加对DB.SQLServer的引用

1  Console.WriteLine("------------------------------------1. 传统方式调用DBHelper中的Query方法--------------------------------------");2  //1.传统的方式调用(需要对 DB.SQLServer添加引用)3  DBHelper db1 = new DBHelper("123");4  db1.Query();

方案二:在Reflection中直接添加对DB.SQLServer、DB.Interface的引用

1   Console.WriteLine("------------------------------------2. 接口的方式调用--------------------------------------");2   //2. 接口的方式调用(只需要引用接口的程序集即可)3   IDBHelper idb1 = new DBHelper("123");4   idb1.Query();

点评:以上两种方案实质上都是通过对相应的实现类添加引用,new出来对象,然后调用方法来实现,没法发布后动态修改数据库。

 方案三:通过反射来创建对象,只需要添加对DB.Interface的引用即可,但需要把DB.SQLServer、DB.MySQL、DB.Oracle的生成dll的目录改成Reflection程序下

1  Console.WriteLine("------------------------------------3. 反射的方式创建对象--------------------------------------");2  //3. 反射的方式创建对象(不需要直接添加对其引用,只需要把相应的程序生成路径改成Reflection中即可)3  Assembly assembly4 = Assembly.Load("DB.SQLServer");4  Type tc = assembly4.GetType("DB.SQLServer.DBHelper");5  //object myDbHelper = Activator.CreateInstance(tc, "123"); //调用带参数的构造函数6  object myDbHelper = Activator.CreateInstance(tc);     //默认调用无参构造函数7  IDBHelper idb2 = (IDBHelper)myDbHelper;8  idb2.Query();

点评:该方案只需要对接口添加引用,符合了面向接口编程的思想,但是发布后在不修改代码的情况下,不能切换数据库。

方案四:IOC(反射+简单工厂+配置文件),需要添加对DB.Interface的引用,并且把DB.SQLServer、DB.MySQL、DB.Oracle的生成dll的目录改成Reflection程序下

配置文件:

1   
2
3
4
5
7
8
10
11
12
13

简单工厂:

1 ///  2     /// 简单工厂,创建对象 3     ///  4     public class SimpleFactory 5     { 6         private static string IDBHelperdllName = ConfigurationManager.AppSettings["IDBHelper-dllName"]; 7         private static string IDBHelperClassName = ConfigurationManager.AppSettings["IDBHelper-className"]; 8  9         public static IDBHelper CreateDBHelper()10         {11             Assembly assembly = Assembly.Load(IDBHelperdllName);12             Type type = assembly.GetType(IDBHelperClassName);13             object obj = Activator.CreateInstance(type);14             return (IDBHelper)obj;15         }16 17     }

调用:

1   Console.WriteLine("------------------------------------4. IOC(反射+简单工厂+配置文件)--------------------------------------");2   //4. IOC(反射+简单工厂+配置文件)(不需要直接添加对其引用,只需要把相应的程序生成路径改成Reflection中即可)3   IDBHelper idb3 = SimpleFactory.CreateDBHelper();4   idb3.Query();

 

 

四. 反射调用实例方法、静态方法、重载方法

1         //2. 实例方法、静态方法、重载方法的调用 2             { 3                 object obj = Activator.CreateInstance(tc5); 4                 Console.WriteLine("---------------------------------2.1 调用无参、有参的实例方法-------------------------------------"); 5                 //2.1 调用无参、有参的实例方法 6                 { 7                     MethodInfo methord = tc5.GetMethod("Show1"); 8                     methord.Invoke(obj, null); 9                 }10                 {11                     MethodInfo methord = tc5.GetMethod("Show2");12                     methord.Invoke(obj, new object[]{
11});13 }14 15 Console.WriteLine("---------------------------------2.2 调用静态方法-------------------------------------");16 //2.2 调用静态方法17 {18 MethodInfo methord = tc5.GetMethod("ShowStatic");19 methord.Invoke(obj, new object[] { "ShowStatic1234" });20 }21 22 Console.WriteLine("---------------------------------2.3 调用重载方法(需要在创建方法的时候,把类型传进去)-------------------------------------");23 //2.3 调用重载方法(需要在创建方法的时候,把类型传进去)24 {25 MethodInfo methord = tc5.GetMethod("Show3", new Type[] { });26 methord.Invoke(obj, null);27 }28 {29 MethodInfo methord = tc5.GetMethod("Show3", new Type[] { typeof(int)});30 methord.Invoke(obj, new object[] { 11 });31 }32 {33 MethodInfo methord = tc5.GetMethod("Show3", new Type[] { typeof(string) });34 methord.Invoke(obj, new object[] { "11" });35 }36 {37 MethodInfo methord = tc5.GetMethod("Show3", new Type[] { typeof(int), typeof(string) });38 methord.Invoke(obj, new object[] { 11 ,"11"});39 }40 {41 MethodInfo methord = tc5.GetMethod("Show3", new Type[] { typeof(string), typeof(int) });42 methord.Invoke(obj, new object[] { "11",11 });43 }44 45 Console.WriteLine("---------------------------------2.4 调用私有方法-------------------------------------");46 //2.4 调用私有方法47 {48 MethodInfo methord = tc5.GetMethod("Show4", BindingFlags.Instance|BindingFlags.NonPublic);49 methord.Invoke(obj, new object[] { "11" });50 }51 Console.WriteLine("---------------------------------2.5 调用泛型方法-------------------------------------");52 //2.5 调用泛型方法53 {54 MethodInfo methord = tc5.GetMethod("ShowGeneric");55 methord = methord.MakeGenericMethod(typeof(string));56 methord.Invoke(obj, new object[] { "123" });57 }58 59 }

五. 反射字段和属性,获取值和设置值

{                //实例化对象                ReflectionTest rTest = new ReflectionTest();                //反射                Assembly assembly5 = Assembly.Load("DB.SQLServer");                Type type5 = assembly5.GetType("DB.SQLServer.ReflectionTest");                object object5 = Activator.CreateInstance(type5);                //1.获取类的所有属性                Console.WriteLine("------------------------------------1.获取类的属性--------------------------------------");                var pInfor= type5.GetProperties();                foreach (var item in pInfor)                {                    Console.WriteLine(item.Name);                    if (item.Name.Equals("Id"))                    {                        item.SetValue(object5, 12332);                    }                }                Console.WriteLine("------------------------------------输出ID属性值--------------------------------------");                rTest = (ReflectionTest)object5;                Console.WriteLine(rTest.Id);                //2.获取类的字段                Console.WriteLine("------------------------------------2.获取类的字段--------------------------------------");                foreach (var item in type5.GetFields(BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public))                {                    Console.WriteLine(item.Name);                }            }

六. 反射的好处和局限

1  { 2                //反射的好处: 3                //反射是.NET中的重要机制,通过反射,可以在运行时获得程序或程序集中每一个类型(包括类、结构、委托、接口和枚举等)的成员和成员的信息。 4                //有了反射,即可对每一个类型了如指掌。另外我还可以直接创建对象,即使这个对象的类型在编译时还不知道。 5  6                 //性能局限 7                 Console.WriteLine("------------------------------测试普通方法和反射的耗时情况--------------------------------------"); 8                 { 9                     //1.普通方法10                     Stopwatch watch = new Stopwatch();11                     watch.Start();12                     for (var i = 0; i < 1000000; i++)13                     {14                         DBHelper2 dh = new DBHelper2();15                         dh.Id = 1;16                         dh.Name = "maru";17                         dh.Query();18                     }19                     watch.Stop();20                     Console.WriteLine("普通方式花费{0}ms:",watch.ElapsedMilliseconds);21                 }22                 {23                     //2. 反射的方法24                     Stopwatch watch = new Stopwatch();25                     watch.Start();26                     Assembly assembley6 = Assembly.Load("DB.SQLServer");27                     Type type6 = assembley6.GetType("DB.SQLServer.DBHelper2");28                     for (var i = 0; i < 1000000; i++)29                     {30                         object obj6 = Activator.CreateInstance(type6);31                         foreach (var item in type6.GetProperties())32                         {33                             if (item.Name.Equals("Id"))34                             {35                                 item.SetValue(obj6, 1);36                             }37                             if (item.Name.Equals("Name"))38                             {39                                 item.SetValue(obj6, "maru");40                             }41                         }42                         MethodInfo m6 = type6.GetMethod("Query");43                         m6.Invoke(obj6, null);44                     }45                     watch.Stop();46                     Console.WriteLine("反射方式花费{0}ms:", watch.ElapsedMilliseconds);47                 }48             }

运行结果:

 七. 补充:获取类的属性、方法、特性、构造函数等,设置属性值,获取属性值

函数                                                                         说明

GetConstructor(s)                  取得此类型的创建函数,其将回传一个ConstructorInfo对象或数组
GetField(s)                             取得此类型中成员变量,其将回传一个FiledInfo对象或数组
GetMember(s)                        取得此类中的成员,其类型可以是变量、事件、属性、方法及Nested Type,其将回传一个MemberInfo对象或数组
GetEvent(s)                            取得此类型中的事件,其将回传一个EventInfo对象或数组
GetProperty/GetProperties         取得此类型中的属性,其将回传一个PropertyInfo对象或数组
GetNestedType(s)                  取得声明于此类型内类型,其将回传一个Type对象或数组
GetCustomAttibutes                    取得绑定于此类型的Attitudes
GetValue(t)                                  获取t对象的的属性值
SetValue(t,"XXX")                        设置t对象的属性值为XXX

实体代码:

1  [Description("我是Person类")] 2     public class Person 3     { 4         //1. 构造函数 5         public Person() 6         { 7  8         } 9         public Person(string sex)10         {11             this._Sex = sex;12         }13         //2. 属性14 15         [Description("我是id")]16         public string id { get; set; }17 18         [ReadOnly(true)]19         public string userName { get; set; }20 21         public string userPwd { get; set; }22 23         //3.成员变量24 25         public string _Sex = null;26 27         public int _Age;28 29         //4. 特性  [Description("我是id")]     [ReadOnly(true)]30 31         //5. 方法32         public string GetOwnSex()33         {34             return this._Sex;35         }36 37         //6. 事件38         public event Action MyEvent;39 40 41 42     }

调用代码:

1  Person person1 = new Person() 2                 { 3                     id = "123", 4                     userName = "ypf", 5                     userPwd = "123456", 6                 }; 7                 //获取类 8                 Type type = person1.GetType(); 9                 {10                     Console.WriteLine("---------------1. 获取构造函数-----------------");11                     ConstructorInfo[] constructorInfoList = type.GetConstructors();12                     for (int i = 0; i < constructorInfoList.Length; i++)13                     {14                         Console.WriteLine(constructorInfoList[i]);15                     }16                 }17                 {18                     Console.WriteLine("---------------2. 获取成员变量-----------------");19                     FieldInfo[] fielInforList = type.GetFields();20                     for (int i = 0; i < fielInforList.Length; i++)21                     {22                         Console.WriteLine(fielInforList[i]);23                     }24                 }25                 {26                     Console.WriteLine("---------------3. 获取成员-----------------");27                     MemberInfo[] memberInfoList = type.GetMembers();28                     for (int i = 0; i < memberInfoList.Length; i++)29                     {30                         Console.WriteLine(memberInfoList[i]);31                     }32                 }33                 {34                     Console.WriteLine("---------------4. 获取事件-----------------");35                     EventInfo[] eventInfoList = type.GetEvents();36                     for (int i = 0; i < eventInfoList.Length; i++)37                     {38                         Console.WriteLine(eventInfoList[i]);39                     }40                 }41                 {42                     Console.WriteLine("---------------5. 获取属性-----------------");43                     PropertyInfo[] propertyInfoList = type.GetProperties();44                     for (int i = 0; i < propertyInfoList.Length; i++)45                     {46                         Console.WriteLine(propertyInfoList[i]);47                     }48                 }49                 {50                     Console.WriteLine("---------------6. 获取特性-----------------");51                     //1. 获取属性上的特性52                     //因为这些测试所用的特性都是加在属性上的,所以要先获取属性53                     PropertyInfo[] propertyInfoList = type.GetProperties();54                     foreach (var item in propertyInfoList)55                     {56                         //获取该属性上的所有特性57                         object[] attributeInfoList = item.GetCustomAttributes(true);58                         foreach (var item2 in attributeInfoList)59                         {60                             Console.WriteLine("{0}属性上的特性为{1}", item, item2);61                         }62 63                     }64                     //2. 获取类上的属性65                     object[] attributeInfoList2 = type.GetCustomAttributes(true);66                     foreach (var item3 in attributeInfoList2)67                     {68                         Console.WriteLine("{0}类上的特性为{1}", type, item3);69                     }       70                 }71                 {72                     Console.WriteLine("---------------7. 获取id属性的值-----------------");73                     PropertyInfo idProperty = type.GetProperty("id");74                     Console.WriteLine("属性名为:{0}", idProperty.Name);75                     Console.WriteLine("属性值为:{0}", idProperty.GetValue(person1));76                     //设置属性值77                     idProperty.SetValue(person1, "2345");78                     Console.WriteLine("设置后的属性值为:{0}", idProperty.GetValue(person1));79 80                 }

结果:

 

转载于:https://www.cnblogs.com/yaopengfei/p/6891286.html

你可能感兴趣的文章
js-ES6学习笔记-Set和Map数据结构
查看>>
Xamarin.Forms的滚动视图ScrollView
查看>>
【面试题整理】数据库的优化方案有哪些
查看>>
hdu-5015-233 Matrix-矩阵
查看>>
Android中asset文件夹和raw文件夹区别与用法
查看>>
poj3264
查看>>
Eclipse中git插件导入远程库和上传项目源代码到远程库
查看>>
linux内核剖析-IBM
查看>>
关于Snmp的Trap代码开发之坑
查看>>
TCP 函数
查看>>
CentOS添加新硬盘到新的分区(xfs/ext4) 或者添加新分区
查看>>
20个Linux服务器安全强化建议(二)
查看>>
php-fpm的启动、配置及常见错误
查看>>
在 Linux 上管理加密密钥的最佳体验
查看>>
值得学习的C语言开源项目
查看>>
SYSTEMTAP -ORACLE
查看>>
[唐诗]183清平调词三首-李白
查看>>
深入敌后,揭开骇客真面目
查看>>
使用 Drag and Drop 给Web应用提升交互体验
查看>>
Flutter 三探
查看>>