Reflection

Reflection是C#程序员的一个最有力工具

最常用的例子来说明反射的用处是一个插件系统。假设你正在创建一个 接受用户创建 的扩展程序,有没有办法预先知道哪些方法这个扩展他们有或有扩展的名字将是什么,除非你可以检查编译的程序集,并在运行时提取信息,这正是反射呢,等等

功能需求

目前,我正在使用Unity开发一个游戏,用户界面是在游戏中(3D UI)。这意味着我会使用Unity提供的API,它提供了相当强大的工具集来创建交互式图形用户界面的。

场景中的3D对象可以响应用户的输入。Unity让你检测鼠标事件,但没有办法用模块化的方法编写单个事件处理程序?

为了得到这个功能,我不得不扩展Unity的Editor和Inspecot 来暴露我的代码,这听起来很复杂,但这些定位方法,并随后调用它们的底层代码很简单。

实现思路及方法

1. 暴露你需要的方法

之前,我们接触过C#的Reflection API,我们需要创建一个新的属性

Attributes allow us to assign metadata to classes, methods, properties, etc. that can be read back by reflection.

属性允许我们指定方法,类属性等等,可以通过反射来读到这些值。

In this case, our attribute is going to be called “ExposeToEditor” and we're going to use it to tag instance methods (and classes with static methods) that Unity's editor should recognise as valid event handlers.

在这种情况下,我们的属性将被称为:ExposeEditor ,我们打算用它来标记Instance(和类的静态方法)Unity的Editor可以识别出它们是有效的事件处理程序

因此,我们创建了一个新的脚本文件,并确保 using Systm;,然后我们编写以下代码:

[AttributeUsage(AttributeTargets.Method | AttributeTargets.Class)]
public class ExposeToEditor : Attribute { }

这将创建一个标准属性系统,我们现在可以分配给任何方法或类,例如:

[ExposeToEditor]
public void OnThisButtonClick(object sender) { };

现在,我们可以放在一起,将跟踪标识以这种方式方法的代码

2. 定位我们的Public的方法

点击上面的图像,将其展开,并期待在最右边的面板中-你会看到一个名为:Interface Click Handler的脚本。这是一个Editor的界面,我们编码,可以让我选择包含我所需要的脚本和方法的特定对象。此图片是更提供上下文是什么,我来解释,而不是使用Reflection的重要组成部分。因此,如果它没有多大,不用担心。

最重要的是这些背后的编辑器界面,它需要定位的方法在脚本的逻辑,下面是关键的部分

var type = t.OnClickMonoBehaviour.GetType(); List<string> methodNames =new List<string>(); List<MethodInfo> methods =new List<MethodInfo>(type.GetMethods()); foreach (MethodInfo mi in methods) { if (mi.IsDefined(typeof(ExposeToEditor), true)) { methods.Add(mi); methodNames.Add(mi.Name); } }

让我们把它分解,我们要做的第一件事情就是,获取选定的脚本类型,后者被存储 在 OnClickMonoBehaviour 对象的属性t。然后我们实例化一些List来存储这些方法的信息,foreach 循环遍历获取所有的包含在这个Script Type的public方法,通过type.GetMethods;

.GetMethods为我们提供一个数组的MethodInfo对象,.MethodInfo包含了大量的关于每个方法的信息,我们可以使用甚至该方法MethofInfo.Invoke.然而,这并不是最有效的方式来动态调用一个方法,以后的东西我会介绍。

现在,我们不希望来存储所有的方法,我们只是想通过那些我们先前创建的属性暴露出来,因此,我们使用MethofInfo.IsDefind() 方法来检查是否 ExposeToEditor 连接到该方法。要彻底,我们告诉 IsDefind 检查继承的类型也是如此。

一旦循环完成之后,我们将不得不包含的方法作为字符串不只是名字,但是这些方法本身,在形式列表 MethofInfo 对象。的字符串列表是用来填充的最后一个影像的”关于Click 方法” 下拉列表中,这样我们就可以很容易地选择正是我们所需要的。

3. 存储和动态调用方法

用方法名存储,所有我们现在需要做的是理清了“Click” 的逻辑,这是用来在游戏中,正如我们前面提到的,要做到这一点最简单的方式是通过使用MethodInfo的动态调用。例如:

MethodInfo mi = VariableContainingMethodInfo;
mi.Invoke();

并没有什么真的错了,这干得不错,但是,我们可以执行通过使用  Action<T> Delegate 并缓存它

首先,我们在某处定义缓存变量

private Action<object> CacheAction;

然后,当界面元件由玩家互动,我们缓存的方法,并用它在随后的相互作用。

CachedAction = (Action<object>)Delegate.CreateDelegate(typeof(Action<object>),OnClickMonoBehaviour,OnClickMethod);

现在,有几个重载 Delegate.CretaeDelegate ,在这种情况下 OnClickMonoBehaviour 和 OnClickMethod 都是字符串。委托创建并存储在CacheAction ,所以当我们要调用它,我们只是这样做:

CacheAction(object);

在这儿 object 只是一个灵活的参数,我们可以根据需要将信息传递到事件处理程序。

The best way to get more familiar with it is to check it out on MSDN. For more practical examples, Stack Exchange is a valuable resource, providing specific examples of how to get reflection doing what you want it to.

Unity[C#] Reflection Use的更多相关文章

  1. Unity By Reflection Update Scripts

    App热更新需求 我正在使用Unity 3D开发一个Android的应用,它会下载AssetBundles并加载它们的内容,但由于AssetBundles不能包含脚本,我将使用预编译的C#脚本,并使用 ...

  2. unity 的reflection probe和environmentmap

    unity做了个很恶心的事情 unity_SpecCube0这里如果在reflectionprobe范围内就传reflectionprobe 如果在probe范围外这里就传environmap 在GI ...

  3. Unity5.5 Lighting Scene

    参考:https://docs.unity3d.com/Manual/GlobalIllumination.html Environment Lighting(环境光) Skybox: 天空盒材质,这 ...

  4. 在Unity中实现屏幕空间反射Screen Space Reflection(1)

    本篇文章我会介绍一下我自己在Unity中实现的SSR效果 出发点是理解SSR效果的原理,因此最终效果不是非常完美的(代码都是够用就行),但是从学习的角度来说足以学习到SSR中的核心算法. 如果对核心算 ...

  5. 在Unity中实现屏幕空间反射Screen Space Reflection(4)

    第四部分讲一下如何在2D屏幕空间步进光线. http://casual-effects.blogspot.com/2014/08/screen-space-ray-tracing.html 中的代码感 ...

  6. unity reflection probe --- forward deferred transparent opaque

    deferred 和forward reflection probe 的差别 deferred ref是逐像素的 forward是逐 obj 但我还遇到一个问题就是box projection ref ...

  7. 【Unity|C#】基础篇(12)——反射(Reflection)(核心类:Type、Assembly)

    [学习资料] <C#图解教程>(第24章):https://www.cnblogs.com/moonache/p/7687551.html 电子书下载:https://pan.baidu. ...

  8. Unity Reflection Probe使用入门

    贴官方API的说法: 反射探头: 一个反射探头很像一个相机,捕获了周围所有方向的球形视图.然后将捕获的图像存储为Cubemap,可由具有反射材料的对象使用.在给定场景中可以使用多个反射探测器,可以将对 ...

  9. 在Unity中实现屏幕空间反射Screen Space Reflection(3)

    本篇讲一下相交检测的优化.有两个措施. 线段相交检测 之前的检测都是检测光线的终点是否在物体内.我们可以尝试检测光线的线段是否与物体相交. 比如说有一个非常薄的物体,光线差不多垂直于它的表面.如果用普 ...

随机推荐

  1. maven-compiler-plugin 指定jdk的版本和编码

    为了让maven的jdk编译版本一致, 使用maven-compiler-plugin插件来协助管理 建议新建maven项目后的第一步就是配置该插件 <build> <plugins ...

  2. centos7.0安装docker-18.06.1-ce不能启动问题

    最近用centos7.0 yum安装了一个docker-ce18.06.1  但是发现安装好不能启动,于是上官网看了一下,说是docker-ce18.06.1是从centos7.2开始支持的,但是7. ...

  3. 2015年第六届蓝桥杯C/C++程序设计本科B组决赛 完美正方形

    完美正方形 如果一些边长互不相同的正方形,可以恰好拼出一个更大的正方形,则称其为完美正方形.历史上,人们花了很久才找到了若干完美正方形.比如:如下边长的22个正方形 2 3 4 6 7 8 12 13 ...

  4. python 使用 matplotlib.pyplot来画柱状图和饼图

    导入包 import matplotlib.pyplot as plt 柱状图 最简柱状图 # 显示高度 def autolabel(rects): for rect in rects: height ...

  5. VMware12 克隆虚拟机并且重新分配ip、mac

    记录如何快速拷贝一台虚拟机,并且重新分配IP.mac等方便自己做实验: 环境:VMWare12  .Redhat6.8 Step1.克隆虚拟机 虚拟机处于未打开状态,右击管理—>克隆 弹出克隆界 ...

  6. 浅谈.net jenkins svn下自动化集成环境安装 搭建 配置

    本人做.net研发已有3年多了,之前一直偏向于技术研究,自己学了很多技术,现在突然发现学了那么多技术有什么用呢?真正用到的并不多. 现在?算是一只小鸟吧,自嘲下.....毕竟我是90后,很多领导对于9 ...

  7. Silverlight 在ie8 下 报2152 错误

    前几天改别人的一个silverlight程序,在项目属性上 选中了 “通过使用应用程序库缓存减小XAP 大小”,编译无错,发布无错误. 放服务器上测试: 站点绑定域名,使用ie9.ie10 都没有问题 ...

  8. ikanalyzer分词,计算信息熵排序分词结果

    因需求,现需分词接口,故记录之. 1.需要依赖: <!-- https://mvnrepository.com/artifact/com.janeluo/ikanalyzer --> &l ...

  9. Oracle空表导出

    执行: Select 'alter table '||table_name||' allocate extent;' from user_tables where num_rows=0 执行该命令后产 ...

  10. Java异常捕获之一道try-catch-finally语句题

    今天,学习了try-catch-finally语句,本来觉得蛮简单.易懂的.搜了一道相关类型的题.结果信心被泼了盆冷水.先把题Mark一下,出去透透风. public class TestEx { p ...