天天看點

Unity[C#] Reflection Use

<a href="http://www.cnblogs.com/zhaoqingqing/p/3848350.html#t0">Reflection</a>

<a href="http://www.cnblogs.com/zhaoqingqing/p/3848350.html#t1">功能需求</a>

<a href="http://www.cnblogs.com/zhaoqingqing/p/3848350.html#t2">實作思路及方法</a>

<a href="http://www.cnblogs.com/zhaoqingqing/p/3848350.html#t3">暴露你需要的方法</a>

<a href="http://www.cnblogs.com/zhaoqingqing/p/3848350.html#t4">定位我們的Public的方法</a>

<a href="http://www.cnblogs.com/zhaoqingqing/p/3848350.html#t5">存儲和動态調用方法</a>

Reflection是C#程式員的一個最有力工具

最常用的例子來說明反射的用處是一個插件系統。假設你正在建立一個 接受使用者建立 的擴充程式,有沒有辦法預先知道哪些方法這個擴充他們有或有擴充的名字将是什麼,除非你可以檢查編譯的程式集,并在運作時提取資訊,這正是反射呢,等等

目前,我正在使用Unity開發一個遊戲,使用者界面是在遊戲中(3D UI)。這意味着我會使用Unity提供的API,它提供了相當強大的工具集來建立互動式圖形使用者界面的。

場景中的3D對象可以響應使用者的輸入。Unity讓你檢測滑鼠事件,但沒有辦法用子產品化的方法編寫單個事件處理程式?

為了得到這個功能,我不得不擴充Unity的Editor和Inspecot 來暴露我的代碼,這聽起來很複雜,但這些定位方法,并随後調用它們的底層代碼很簡單。

Unity[C#] Reflection Use

之前,我們接觸過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;,然後我們編寫以下代碼:

這将建立一個标準屬性系統,我們現在可以配置設定給任何方法或類,例如:

現在,我們可以放在一起,将跟蹤辨別以這種方式方法的代碼

Unity[C#] Reflection Use

點選上面的圖像,将其展開,并期待在最右邊的面闆中-你會看到一個名為:Interface Click Handler的腳本。這是一個Editor的界面,我們編碼,可以讓我選擇包含我所需要的腳本和方法的特定對象。此圖檔是更提供上下文是什麼,我來解釋,而不是使用Reflection的重要組成部分。是以,如果它沒有多大,不用擔心。

最重要的是這些背後的編輯器界面,它需要定位的方法在腳本的邏輯,下面是關鍵的部分

var type = t.OnClickMonoBehaviour.GetType(); List&lt;string&gt; methodNames =new List&lt;string&gt;(); List&lt;MethodInfo&gt; methods =new List&lt;MethodInfo&gt;(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 方法” 下拉清單中,這樣我們就可以很容易地選擇正是我們所需要的。

用方法名存儲,所有我們現在需要做的是理清了“Click” 的邏輯,這是用來在遊戲中,正如我們前面提到的,要做到這一點最簡單的方式是通過使用MethodInfo的動态調用。例如:

并沒有什麼真的錯了,這幹得不錯,但是,我們可以執行通過使用  Action&lt;T&gt; Delegate 并緩存它

首先,我們在某處定義緩存變量

private Action&lt;object&gt; CacheAction;

然後,當界面元件由玩家互動,我們緩存的方法,并用它在随後的互相作用。

CachedAction = (Action&lt;object&gt;)Delegate.CreateDelegate(typeof(Action&lt;object&gt;),OnClickMonoBehaviour,OnClickMethod);

現在,有幾個重載 Delegate.CretaeDelegate ,在這種情況下 OnClickMonoBehaviour 和 OnClickMethod 都是字元串。委托建立并存儲在CacheAction ,是以當我們要調用它,我們隻是這樣做:

CacheAction(object);

在這兒 object 隻是一個靈活的參數,我們可以根據需要将資訊傳遞到事件處理程式。

本文轉自趙青青部落格園部落格,原文連結:http://www.cnblogs.com/zhaoqingqing/p/3848350.html,如需轉載請自行聯系原作者

繼續閱讀