博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
10分钟教你理解反射
阅读量:5871 次
发布时间:2019-06-19

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

什么是反射?

反射反射,程序员的快乐,在.Net领域程序设计中,反射是无处不在的,MVCASP.Net、各种ORMIOCAOP几乎所有的框架都离不开反射。反编译工具使用的底层技术用的不是反射,是一种逆向工程。

反射(ReflectionSystem.Reflection),是.Net Framework提供的一个帮助类库,可以读取并使用Metadata中描述的数据信息。元数据(Metadata),描述了dll/exe里面的各种信息,又称中介数据、中继数据,为描述的数据(data about data),主要是描述数据property)的,用来支持如指示存储位置、数据、查找、文件记录等功能。

反射的优缺点:

优点:动态—在不破坏原有程序的情况下,可对程序进行良好的扩展。Eg:我们有这样一需求,项目在最初的时候用的是Mysql数据库,由于项目情况变化需要更换成SqlServer数据库。面对这种项目的需求,传统的解决方法是在项目中添加新的SqlServer数据库访问代码,将数据库访问实现层更改为SqlServer,最后编译源代码并重新发布。

传统解决方法示例伪代码如下:

1                     IDBHelper iDBHelper = new MySqlHelper();2                     IDBHelper iDBHelper = new SqlServerHelper();3                     iDBHelper.Query();

使用反射的示例代码:

1 namespace ReflectionDemo 2 { 3     ///  4     /// 反射工厂 5     ///  6     public class SimpleFactory 7     { 8         //读取配置文件 9         private static string IDBHelperConfig = ConfigurationManager.AppSettings["IDBHelperConfig"];10         //获取需要加载的dll名称11         private static string DllName = IDBHelperConfig.Split(',')[0]; 12         //获取需要的类型名称13         private static string TypeName = IDBHelperConfig.Split(',')[1];14         /// 15         /// 通过反射动态加载与类型名称相匹配的实例16         /// 17         /// 
18 public static IDBHelper CreateInstance()19 {20 Assembly assembly = Assembly.Load(DllName);21 Type type = assembly.GetType(TypeName);22 object oDBHelper = Activator.CreateInstance(type);23 IDBHelper iDBHelper = oDBHelper as IDBHelper;24 return iDBHelper;25 }26 }27 }
IDBHelper iDBHelper = SimpleFactory.CreateInstance();                iDBHelper.Query();

通过反射实现了程序的可配置,通过修改配置文件就可以自动切换实现类,实现类必须是事先已有的, 没有将实现类固定,而是通过配置文件执行,通过反射创建的。可扩展:完全不修改原有代码,只是增加新的实现、修改配置文件,就可以支持新功能。这就是反射的动态特性。

缺点:使用麻烦、避开编译器检查导致运程序行时异常变多、性能问题。

通过反射调用构造函数

1 namespace SqlServerDb  2 {  3   4     ///   5     /// 反射测试类  6     ///   7     public class ReflectionTest  8     {  9         #region Identity 10         ///  11         /// 无参构造函数 12         ///  13         public ReflectionTest() 14         { 15             Console.WriteLine("这里是{0}无参数构造函数", this.GetType()); 16         } 17  18         ///  19         /// 带参数构造函数 20         ///  21         ///  22         public ReflectionTest(string name) 23         { 24             Console.WriteLine("这里是{0} 有参数【string】构造函数", this.GetType()); 25         } 26  27         public ReflectionTest(int id) 28         { 29             Console.WriteLine("这里是{0} 有参数【int】构造函数", this.GetType()); 30         } 31         #endregion 32  33         #region Method 34         ///  35         /// 无参方法 36         ///  37         public void Show1() 38         { 39             Console.WriteLine("这里是{0}的Show1", this.GetType()); 40         } 41         ///  42         /// 有参数方法 43         ///  44         ///  45         public void Show2(int id) 46         { 47  48             Console.WriteLine("这里是{0}的Show2", this.GetType()); 49         } 50         ///  51         /// 重载方法之一 52         ///  53         ///  54         ///  55         public void Show3(int id, string name) 56         { 57             Console.WriteLine("这里是{0}的Show3", this.GetType()); 58         } 59         ///  60         /// 重载方法之二 61         ///  62         ///  63         ///  64         public void Show3(string name, int id) 65         { 66             Console.WriteLine("这里是{0}的Show3_2", this.GetType()); 67         } 68         ///  69         /// 重载方法之三 70         ///  71         ///  72         public void Show3(int id) 73         { 74             Console.WriteLine("这里是{0}的Show3_3", this.GetType()); 75         } 76         ///  77         /// 重载方法之四 78         ///  79         ///  80         public void Show3(string name) 81         { 82             Console.WriteLine("这里是{0}的Show3_4", this.GetType()); 83         } 84  85         ///  86         /// 重载方法之五 87         ///  88         public void Show3() 89         { 90             Console.WriteLine("这里是{0}的Show3_1", this.GetType()); 91         } 92  93         ///  94         /// 私有方法 95         ///  96         ///  97         private void Show4(string name) 98         { 99             Console.WriteLine("这里是{0}的Show4", this.GetType());100         }101 102         /// 103         /// 静态方法104         /// 105         /// 106         public static void Show5(string name)107         {108             Console.WriteLine("这里是{0}的Show5", typeof(ReflectionTest));109         }110         #endregion111     }112 }
1                 Assembly assembly = Assembly.Load("SqlServerDb"); 2                 Type type = assembly.GetType("SqlServerDb.ReflectionTest"); 3                 foreach (ConstructorInfo ctor in type.GetConstructors()) 4                 { 5                     Console.WriteLine($"ctor.Name:{ctor.Name}"); 6                     foreach (var parameter in ctor.GetParameters()) 7                     { 8                         Console.WriteLine($"ParameterType:{parameter.ParameterType},parameterName: {parameter.Name}"); 9                     }10                 }11                 object oTest1 = Activator.CreateInstance(type);12                 object oTest2 = Activator.CreateInstance(type, new object[] { 123 });13                 object oTest3 = Activator.CreateInstance(type, new object[] { "陌殇" });

 反射破坏单例

1                 //反射破坏单例---就是反射调用私有构造函数2                 Assembly assembly = Assembly.Load("SqlServerDb");3                 Type type = assembly.GetType("SqlServerDb.Singleton");4                 Singleton singletonA = (Singleton)Activator.CreateInstance(type, true);5                 Singleton singletonB = (Singleton)Activator.CreateInstance(type, true);6                 Console.WriteLine($"{object.ReferenceEquals(singletonA, singletonB)}");

反射调用泛型类

namespace SqlServerDb{    ///     /// 泛型测试类    ///     /// 
///
///
public class GenericClass
{ public GenericClass() { Console.WriteLine("GenericClass
的构造函数被调用了"); } public void Show(T t, W w, X x) { Console.WriteLine("t.type={0},w.type={1},x.type={2}", t.GetType().Name, w.GetType().Name, x.GetType().Name); } } ///
/// 泛型测试方法 /// public class GenericMethod { public GenericMethod() { Console.WriteLine("GenericMethod类的构造函数被调用了。"); } public void Show
(T t, W w, X x) { Console.WriteLine("t.type={0},w.type={1},x.type={2}", t.GetType().Name, w.GetType().Name, x.GetType().Name); } } public class GenericDouble
{ public void Show
(T t, W w, X x) { Console.WriteLine("t.type={0},w.type={1},x.type={2}", t.GetType().Name, w.GetType().Name, x.GetType().Name); } }}
1                 Assembly assembly = Assembly.Load("SqlServerDb");2                 Type type = assembly.GetType("SqlServerDb.GenericClass`3");3                 GenericClass
genericClass = new GenericClass
();4 //genericClass.Show("12", 1, DateTime.Now);5 //object oGeneric = Activator.CreateInstance(type);6 Type typeMake = type.MakeGenericType(new Type[] { typeof(string), typeof(int), typeof(DateTime) });7 object oGeneric = Activator.CreateInstance(typeMake);

反射调用泛型方法

Assembly assembly = Assembly.Load("SqlServerDb");                Type type = assembly.GetType("SqlServerDb.GenericMethod");                object oGeneric = Activator.CreateInstance(type);

如果反射创建对象之后,知道方法名称,怎么样不做类型转换,直接调用方法?

1    2                 Assembly assembly = Assembly.Load("SqlServerDb"); 3                 Type type = assembly.GetType("SqlServerDb.ReflectionTest"); 4                 object oTest = Activator.CreateInstance(type); 5                 foreach (var method in type.GetMethods()) 6                 { 7                     Console.WriteLine(method.Name); 8                     foreach (var parameter in method.GetParameters()) 9                     {10                         Console.WriteLine($"{parameter.Name}  {parameter.ParameterType}");11                     }12                 }13                 {14                     ReflectionTest reflection = new ReflectionTest();15                     reflection.Show1();16                 }17                 {18                     MethodInfo method = type.GetMethod("Show1");19                     //if()20                     method.Invoke(oTest, null);21                 }22                 {23                     MethodInfo method = type.GetMethod("Show2");24                     method.Invoke(oTest, new object[] { 123 });25                 }26                 {27                     MethodInfo method = type.GetMethod("Show3", new Type[] { });28                     method.Invoke(oTest, null);29                 }30                 {31                     MethodInfo method = type.GetMethod("Show3", new Type[] { typeof(int) });32                     method.Invoke(oTest, new object[] { 123 });33                 }34                 {35                     MethodInfo method = type.GetMethod("Show3", new Type[] { typeof(string) });36                     method.Invoke(oTest, new object[] { "一生为你" });37                 }38                 {39                     MethodInfo method = type.GetMethod("Show3", new Type[] { typeof(int), typeof(string) });40                     method.Invoke(oTest, new object[] { 234, "心欲无痕" });41                 }42                 {43                     MethodInfo method = type.GetMethod("Show3", new Type[] { typeof(string), typeof(int) });44                     method.Invoke(oTest, new object[] { "PHS", 345 });45                 }46                 {47                     MethodInfo method = type.GetMethod("Show5");48                     method.Invoke(oTest, new object[] { "张中魁" });//静态方法实例可以要49                 }50                 {51                     MethodInfo method = type.GetMethod("Show5");52                     method.Invoke(null, new object[] { "张中魁" });//静态方法实例也可以不要53                 }

反射调用私有方法

1             {2                 //调用私有方法3                 Console.WriteLine("&&&&&&&&&&&&&&&&&&&&私有方法&&&&&&&&&&&&&&&&&&&");4                 Assembly assembly = Assembly.Load("SqlServerDb");5                 Type type = assembly.GetType("SqlServerDb.ReflectionTest");6                 object oTest = Activator.CreateInstance(type);7                 var method = type.GetMethod("Show4", BindingFlags.Instance | BindingFlags.NonPublic);8                 method.Invoke(oTest, new object[] { "我是老王" });9             }

反射调用泛型方法

Assembly assembly = Assembly.Load("SqlServerDb");                Type type = assembly.GetType("SqlServerDb.GenericMethod");                object oGeneric = Activator.CreateInstance(type);                foreach (var item in type.GetMethods())                {                    Console.WriteLine(item.Name);                }                MethodInfo method = type.GetMethod("Show");                //指定泛型方法的参数类型                var methodNew = method.MakeGenericMethod(new Type[] { typeof(int), typeof(string), typeof(DateTime) });                object oReturn = methodNew.Invoke(oGeneric, new object[] { 123, "董小姐", DateTime.Now });

反射调用泛型方法加泛型类

1                 Assembly assembly = Assembly.Load("SqlServerDb");2                 //在获取类型的同时通过MakeGenericType指定泛型的参数类型3                 Type type = assembly.GetType("SqlServerDb.GenericDouble`1").MakeGenericType(typeof(int));4                 object oObject = Activator.CreateInstance(type);5                 MethodInfo method = type.GetMethod("Show").MakeGenericMethod(typeof(string), typeof(DateTime));6                 method.Invoke(oObject, new object[] { 345, "感谢有梦", DateTime.Now });

 

转载于:https://www.cnblogs.com/netlws/p/11001218.html

你可能感兴趣的文章
How can I set ccshared=-fPIC while executing ./configure?
查看>>
2.移植uboot-添加2440单板,并实现NOR、NAND启动
查看>>
hadoop-2.6.5安装
查看>>
vmware虚拟机里的LINUX不能上网的原因一:虚拟网卡设置
查看>>
监控摄像机的区别和分类
查看>>
Java学习——对象和类
查看>>
ElasticSearch 组合过滤器
查看>>
HttpClient连接池的连接保持、超时和失效机制
查看>>
eigrp debug命令详解
查看>>
NFS配置文件
查看>>
J2ME程序员容易遇到的问题!不断更新中_2008.05.17
查看>>
实例标识助力您的应用迁上云端
查看>>
1-4 多文档界面处理(2)
查看>>
使用Weka进行数据挖掘
查看>>
《Essential Linux Device Drivers》中文版第1章
查看>>
让远程传输大文件变得更快
查看>>
WEB程序调用客户端程序
查看>>
Linux 下的 sleep
查看>>
System.Convert 的一些事
查看>>
你真的会玩SQL吗?玩爆你的数据报表之存储过程编写(下)
查看>>