博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
C# 反射研究
阅读量:4540 次
发布时间:2019-06-08

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

概念

反射这东西,对于我这种小白,听起来总是觉得好大上的。

当初理解它费了一点时间,后来看了一句话,突然恍然大悟,“反射就跟B超一样,我们在不剖开人体的情况下想看清楚内部情况,

我们就通过发射超声波,然后根据超声波反射回来的情况,描绘出人体内部的细节”。

比喻得很形象呢呵呵,C#的反射也差不多这样,我们想要探究一个类(或程序集)内部的情况,

但我们又没有权限进入内部查看,于是我们用反射,然后获取该程序集内部的情况,达到使用引用他的目的。

 

这是比较官方化的定义:反射就是审查元数据并收集关于它的类型信息的能力。元数据(编译以后的最基本数据单元)

就是一大堆的表,当编译程序集或者模块时,编译器会创建一个类定义表,一个字段定义表,和一个方法定义表等。

 

 

作用

反射的作用,说白了就是在程序运行时可以动态获取其他程序集(dll)等的内部情况,然后可以动态加载并使用他们。

1、最常见的一个做法,就是插件。.Net程序的插件写法就是:你预留一些接口,然后编写插件的人根据你预留的接口写插件,

并将编译好的dll放到对应文件夹,那么你的程序运行时就会用反射动态加载使用这些插件。

2、还有一个很牛逼的做法就是可以达到修改程序一些行为的目的,例如Unity的Editor,虽然支持编程插件,但一些API并不对外

开放,你可以通过反编译Unity的dll(前提是你反编译得了),然后获取某个功能是用什么API完成的,然后通过反射加载Editor

的dll,并根据上一步获取的API用法,自己来使用这些不公开的API。

参考雨松MONO的博客:

3、另一个用法就是可以通过函数名加载函数拉,比如本人最近在做一个插件(类PlayMaker的可视化FSM插件),里面有个功能类,

这个功能类里有许多的函数,每个函数对应一个功能,然后在程序运行时会将这些函数映射到屏幕上的一个列表里,你点击列表里的

哪个按钮,就执行哪个函数。虽然可以通过为每个函数绑定一个Button实现,但比如函数非常多,这样就忙不过来了,而且达不到可以

动态修改的目的。比如你以后要多添加几个功能函数,那么又要为它们绑定几个按钮。我的想法就是在创建列表的时候扫描这个类,

将这个类的所有函数列出来,然后为他们绑定按钮。反射帮助了我。(大误:刚刚百度了下,才知道通过函数名加载函数没必要用反射,

直接Type.GetMethod就能返回函数数组了,反射性能不高,没必要用)

参考我这篇文章的第六点:

注:顺便一说,Unity里的SendMessage就是通过反射调用回调函数的,SendMessage("Methon Name");

 

 

使用

//获取类型信息     Type type = typeof(MyClass);     Response.Write("类型名:" + type.Name);     Response.Write("类全名:" + type.FullName);     Response.Write("命名空间名:" + type.Namespace);     Response.Write("程序集名:" + type.Assembly);     Response.Write("模块名:" + type.Module);     Response.Write("基类名:" + type.BaseType);     Response.Write("是否类:" + type.IsClass);     Response.Write("类的公共成员:");     //得到所有公共成员     MemberInfo[] memberInfos = type.GetMembers();     foreach (var item in memberInfos)         Response.Write(string.Format("成员类型" + item.MemberType));
//获取当前执行代码的程序集    Assembly assem = Assembly.GetExecutingAssembly();     Response.Write("程序集全名:"+assem.FullName);    Response.Write("程序集的版本:"+assem.GetName().Version);    Response.Write("程序集初始位置:"+assem.CodeBase);    Response.Write("程序集位置:"+assem.Location);    Response.Write("程序集入口:"+assem.EntryPoint);     Type[] types = assem.GetTypes();    Response.Write("程序集下包含的类型:");    foreach (var item in types)    {        Response.Write("类:"+item.Name);    }
// 动态加载Dll并反射调用程序集中的方法 protected void Page_Load(object sender, EventArgs e){       System.Reflection.Assembly ass = Assembly.LoadFrom(AppDomain.CurrentDomain.BaseDirectory+"bin\\Test.dll"); //加载DLL     System.Type t = ass.GetType("Test.MyClass");//获得类型      string name = typeof(MyClass).AssemblyQualifiedName;     System.Type t1 = Type.GetType(name);   System.Type t2 = typeof(MyClass);      object o = System.Activator.CreateInstance(t);//创建实例     System.Reflection.MethodInfo mi = t.GetMethod("Fun_1");//获得方法     mi.Invoke(o, new object[] { this.Page, "alert('测试反射机制')" });//调用方法      System.Reflection.MethodInfo mi1 = t.GetMethod("Fun_2");     mi1.Invoke(t, new object[] { this.Page, "alert('测试反射机制1')" });//调用方法 }
// 获取某个类的所有子类var allTypes = Assembly.Load("Assembly-CSharp").GetTypes();var childTypes = allTypes.Where(type => type.IsSubclassOf(typeof(ParentType))).ToList();

 

 

动态创建类

(待编辑)

动态编译,参考这篇文章:

 

 

反射与工厂模式

(待编辑)

 

 

参考文章:

转载于:https://www.cnblogs.com/jeason1997/p/5142840.html

你可能感兴趣的文章
1005 继续(3n+1)猜想 (25 分)
查看>>
【洛谷P1641】[SCOI2010]生成字符串
查看>>
2014.8.15模拟赛【公主的朋友】
查看>>
Linux常用系统信息查看命令
查看>>
系统全局环境变量设置
查看>>
JSCS: Please specify path to 'JSCS' package
查看>>
[Matlab.Matrix] 作为判断条件
查看>>
java设计模式--迭代器模式
查看>>
Vim 的粘贴复制功能
查看>>
C#学习资料
查看>>
web标签语义化
查看>>
iOS运行时 归档
查看>>
js获取当前网页header头部信息
查看>>
linux复习一
查看>>
系统特殊路径一览
查看>>
R语言演示功能
查看>>
深入理解Lua的闭包一:概念、应用和实现原理
查看>>
Entity Framework Code First属性映射约定
查看>>
Objective-C代码混淆
查看>>
【代码笔记】iOS-gif图片播放
查看>>