10分钟教你理解反射

什么是反射?

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

反射(Reflection、System.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     /// <summary>
 4     /// 反射工厂
 5     /// </summary>
 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         /// <summary>
15         /// 通过反射动态加载与类型名称相匹配的实例
16         /// </summary>
17         /// <returns></returns>
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 }
  <add key="IDBHelperConfig" value="MySqlDb,MySqlDb.MySqlHelper"/>
                IDBHelper iDBHelper = SimpleFactory.CreateInstance();
                iDBHelper.Query();

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

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

通过反射调用构造函数

  1 namespace SqlServerDb
  2 {
  3
  4     /// <summary>
  5     /// 反射测试类
  6     /// </summary>
  7     public class ReflectionTest
  8     {
  9         #region Identity
 10         /// <summary>
 11         /// 无参构造函数
 12         /// </summary>
 13         public ReflectionTest()
 14         {
 15             Console.WriteLine("这里是{0}无参数构造函数", this.GetType());
 16         }
 17
 18         /// <summary>
 19         /// 带参数构造函数
 20         /// </summary>
 21         /// <param name="name"></param>
 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         /// <summary>
 35         /// 无参方法
 36         /// </summary>
 37         public void Show1()
 38         {
 39             Console.WriteLine("这里是{0}的Show1", this.GetType());
 40         }
 41         /// <summary>
 42         /// 有参数方法
 43         /// </summary>
 44         /// <param name="id"></param>
 45         public void Show2(int id)
 46         {
 47
 48             Console.WriteLine("这里是{0}的Show2", this.GetType());
 49         }
 50         /// <summary>
 51         /// 重载方法之一
 52         /// </summary>
 53         /// <param name="id"></param>
 54         /// <param name="name"></param>
 55         public void Show3(int id, string name)
 56         {
 57             Console.WriteLine("这里是{0}的Show3", this.GetType());
 58         }
 59         /// <summary>
 60         /// 重载方法之二
 61         /// </summary>
 62         /// <param name="name"></param>
 63         /// <param name="id"></param>
 64         public void Show3(string name, int id)
 65         {
 66             Console.WriteLine("这里是{0}的Show3_2", this.GetType());
 67         }
 68         /// <summary>
 69         /// 重载方法之三
 70         /// </summary>
 71         /// <param name="id"></param>
 72         public void Show3(int id)
 73         {
 74             Console.WriteLine("这里是{0}的Show3_3", this.GetType());
 75         }
 76         /// <summary>
 77         /// 重载方法之四
 78         /// </summary>
 79         /// <param name="name"></param>
 80         public void Show3(string name)
 81         {
 82             Console.WriteLine("这里是{0}的Show3_4", this.GetType());
 83         }
 84
 85         /// <summary>
 86         /// 重载方法之五
 87         /// </summary>
 88         public void Show3()
 89         {
 90             Console.WriteLine("这里是{0}的Show3_1", this.GetType());
 91         }
 92
 93         /// <summary>
 94         /// 私有方法
 95         /// </summary>
 96         /// <param name="name"></param>
 97         private void Show4(string name)
 98         {
 99             Console.WriteLine("这里是{0}的Show4", this.GetType());
100         }
101
102         /// <summary>
103         /// 静态方法
104         /// </summary>
105         /// <param name="name"></param>
106         public static void Show5(string name)
107         {
108             Console.WriteLine("这里是{0}的Show5", typeof(ReflectionTest));
109         }
110         #endregion
111     }
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
{

    /// <summary>
    /// 泛型测试类
    /// </summary>
    /// <typeparam name="T"></typeparam>
    /// <typeparam name="W"></typeparam>
    /// <typeparam name="X"></typeparam>
    public class GenericClass<T, W, X>
    {
        public GenericClass()
        {
            Console.WriteLine("GenericClass<T, W, X>的构造函数被调用了");
        }

        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);
        }
    }

    /// <summary>
    /// 泛型测试方法
    /// </summary>
    public class GenericMethod
    {

        public GenericMethod()
        {
            Console.WriteLine("GenericMethod类的构造函数被调用了。");
        }

        public void Show<T, W, X>(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<T>
    {
        public void Show<W, X>(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<string, int, DateTime> genericClass = new GenericClass<string, int, DateTime>();
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

时间: 2024-11-05 12:27:34

10分钟教你理解反射的相关文章

【数据结构】10分钟教你用栈求解迷宫老鼠问题超详细教程附C++源代码

问题描述 给定一张迷宫地图和一个迷宫入口,然后进入迷宫探索找到一个出口.如下图所示: 该图是一个矩形区域,有一个入口和出口.迷宫内部包含不能穿越的墙壁或者障碍物.这些障碍物沿着行和列放置,与迷宫的边界平行.迷宫的入口在左上角,出口在右下角. 问题分析 首先要有一张迷宫地图,地图由两部分组成: (1)一是迷宫中各处的位置坐标, (2)二是迷宫各位置处的状态信息,即该处是墙还是路 所以,该迷宫地图可由一个二维数组来表示.数组的横纵坐标表示迷宫各处的位置坐标,数组元素表示各位置处的状态信息. 2.在这

10分钟教你用python打造贪吃蛇超详细教程

10分钟教你用python打造贪吃蛇超详细教程 在家闲着没妹子约, 刚好最近又学了一下python,听说pygame挺好玩的.今天就在家研究一下, 弄了个贪吃蛇出来.希望大家喜欢. 先看程序效果: 01 整体框架 平台:pycharm 关于pygame的安装这里就不在赘述,大家自行上网找合适自己的版本的安装即可.关于pygame模块知识会穿插在下面代码中介绍,用到什么就介绍什么.这里就不统一介绍了. 整个程序由于是调用了大量的pygame里面的库函数,所以也非常简单(卧槽你这不是调包侠嘛).也就

【python】10分钟教你用python如何正确把妹

前言 今天没妹子约,刚好朋友研究一下python.让他教大家如何用神奇的python打造一个把妹神器吧.看完这个,你们就能走向人生巅峰,迎娶白富美啦. 我知道你们想看看效果 当然啦,这只是测试版的效果,真正的版本可比这个厉害多啦.不过作为一个直男,另一个男的给小编发这个测试感觉还是有点怪怪的哈. 文:吉柏言 暑假来了,各位又不得不和男女朋友暂时分开2个月了!!长达两个月的时间里不能相见,你可知我多想你啊,想知道你的城市下雨了吗,想知道你带伞了吗,想知道你长什么样,想知道你叫啥,咳咳,单身汪小编表

10分钟教你用Python玩转微信之抓取好友个性签名制作词云

01 前言+展示 各位小伙伴我又来啦.今天带大家玩点好玩的东西,用Python抓取我们的微信好友个性签名,然后制作词云.怎样,有趣吧~好了,下面开始干活.我知道你们还是想先看看效果的. 后台登录: 词云: 02 环境准备 Python版本:3.6.0系统平台:Windows 10 X64IDE:pycharm 相关模块:re模块:itchat模块:jieba模块:import matplotlib.pyplot模块:wordcloud模块:以及一些Python自带的模块. 03 获取个性签名 首

10分钟教你拥有可编程QQ机器人

10分钟教你拥有可编程QQ机器人 --酷Q Air教程 --BY dudujerry 要想阅读本篇教程,读者需要基本的C++知识以及Visual Studio 2010/2015/2017 首先,需要从官方网站下载软件 https://cqp.cc/t/23253 .下载后从"下载"/"Download"文件夹中找到其压缩包.解压. 然后,我们从Github中下载酷Q的SDK. https://github.com/CoolQ/cqsdk-vc 解压发现.sln,是

10分钟教你用Python做个打飞机小游戏超详细教程

更多精彩尽在微信公众号[程序猿声] 我知道你们一定想先看效果如何 00 目录 整体框架 开始之前-精灵类Sprite 子弹类class Bullet 玩家飞机类class Player 敌机类class Enemy 游戏主体循环以及帧率设置 让子弹飞 刷出敌机 打怪 把飞机敌机子弹都画出来 处理键盘事件 分数显示 和 GameOver 最终代码 01 前言 这次还是用python的pygame库来做的游戏.关于这个库的内容,读者可以上网了解一下.本文只讲解用到的知识.代码参考自网上,自己也做了一

【python】10分钟教你用python一行代码搞点大新闻

准备 相信各位对python的语言简洁已经深有领会了.那么,今天就带大家一探究竟.看看一行python代码究竟能干些什么大新闻.赶紧抄起手中的家伙,跟我来试试吧. 首先你得先在命令行进入python.像下面一样. 1> python2Python 3.6.0 (v3.6.0:41df79263a11, Dec 23 2016, 08:06:12) [MSC v.1900 64 bit (AMD64)] on win323Type "help", "copyright&q

10分钟教你看懂mongodb的npm包

最近刚开始接触node.js,在做一个博客,在学习过程中,肯定是接触了不少npm的包,主要就是学习使用它的API.现在所写的就是关于mongodb的使用.首先mongodb这个包是用来提供连接和操作mongdb这个数据库的包,如果你的后台数据库是采用的mongodb那么我们将要用到这个包. 首先我们在npm中去搜索这个包,就是第一个 我们点进去去看他的具体信息,我们直接看它的API手册 然后该文档的主页介绍了里面的一些资源文件(js文件)的大致作用:http://mongodb.github.i

“猜你喜欢”的背后揭秘--10分钟教你用Python打造推荐系统

欲直接下载代码文件,关注我们的公众号哦!查看历史消息即可! 话说,最近的瓜实在有点多,从我科校友李雨桐怒锤某男.陈羽凡吸毒被捕.蒋劲夫家暴的三连瓜,到不知知网翟博士,再到邓紫棋解约蜂鸟.王思聪花千芳隔空互怼. 而最近的胜利夜店.张紫妍巨瓜案.最强大脑选手作弊丑闻,更是让吃瓜群众直呼忙不过来:瓜来的太快就像龙卷风,扶我起来,我还能吃! 说到底,这其实是一个信息过载的时代:公众号每天数十条的推送.朋友圈的晒娃晒旅游.各种新闻报道扑面而来令人眼花缭乱.目不暇接-- 那么问题来了,怎么找到自己的关注点呢