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. Charles抓包之HTTPS抓包配置

    访问我的博客 前言 由于工作中经常需要配置客户端开发人员对接接口,有时候对接地不太顺利,因此需要经常性地对公司 APP 进行抓包看请求,找出具体的原因. 在公司中开发使用的 Windows 台式电脑, ...

  2. postgresql 清空数据表数据

    在 mysql中,只需要执行: TRUNCATE table_name; 即可,数据会情况,而且自增id也会变回0: 但在 postgresql 则稍有不同,因为 postgresql 的自增id是通 ...

  3. Conditional特性用法

    说明:根据预处理标识符执行方法.Conditional 特性是 ConditionalAttribute 的别名,可应用于方法或属性类.相对于#if和#endif,更灵活更简洁和不易出错. 例如: # ...

  4. <context:component-scan>子标签:<context:include-filter>和<context:exclude-filter>使用时要注意的地方

    在Spring MVC中的配置中一般会遇到这两个标签,作为<context:component-scan>的子标签出现. 但在使用时要注意一下几点: 1.在很多配置中一般都会吧Spring ...

  5. Python web 框架之 Django 基础搭建服务

    1. 需要安装 Python 和 Django 环境,Python 环境的安装我就不在多说了 2. 安装框架 Django Django 安装,推荐先装个 pip吧,easyinstall也可以,然后 ...

  6. C# Owin 创建与测试自己的中间件Middleware(二)

    本文纯属介绍怎么简单地创建自己的Owin.还没有理解owin概念的请看上一篇文章:http://www.cnblogs.com/alunchen/p/7049307.html 目录 1.创建项目 2. ...

  7. .netcore入门

    开发环境:windows    编辑器: Visual Studio Code 环境安装: .Net Core 1.1 SDK     https://www.microsoft.com/net/co ...

  8. VS2010 的 HTML 5验证

    前言 VS2010的HTML验证中,没有我们的HTML 5,网上我看到使用vs2010 sp1补丁的方法,但是我的安装不了,后来发现下面的方法,让你的vs2010具有html5的验证功能. 下载这个文 ...

  9. 【Linux】 源码安装make命令详解,避免踩坑

    正常的编译安装/卸载: 源码的安装一般由3个步骤组成:配置(configure).编译(make).安装(make install).   configure文件是一个可执行的脚本文件,它有很多选项, ...

  10. 过滤器模式(Filter Pattern)

    过滤器模式 一.什么是过滤器模式   过滤器模式(Filter Pattern),这种模式允许开发人员使用不同的标准来过滤一组对象,通过逻辑运算以解耦的方式把它们连接起来.这种类型的设计模式属于结构型 ...