[英]Reflection C# - How to get handle to class several properties deep
我不是OOP的新手,而是反射的新手。 我確定我錯過了一些簡單的東西,並且在發布之前已經嘗試了一段時間。
我一直試圖獲取對字段的訪問,包括獲取和設置其值。 問題是該字段位於類的屬性內。
以下代碼獲取了一個現有窗口,並在類中進行了更深入的研究,直到碰壁。 最終,我想在TreeViewGUI的現有實例中獲取並設置“ k_LineHeight”。
以下代碼帶有大量注釋。 感謝您抽出寶貴的時間對此進行研究。 在Unity的Mono Debug.Log()中,等效於寫入控制台。
// Get the assembly
Assembly asm = typeof(UnityEditor.EditorWindow).Assembly;
Debug.Log (asm + "\n"); // returns -> UnityEditor, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null
// Get the Type of SceneHierarchyWindow from 'asm'
Type wndType = asm.GetType("UnityEditor.SceneHierarchyWindow");
Debug.Log (wndType + "\n"); // returns -> UnityEditor.SceneHierarchyWindow <- Type
// 'GetWindow' retrieves the ACTIVE instance of the windows currently open
EditorWindow wnd = EditorWindow.GetWindow(wndType);
Debug.Log (wnd + "\n"); // returns -> U (UnityEditor.SceneHierarchyWindow) <- Active Object
// Retrieves the ACTIVE TreeView class stored in 'treeView' from 'wnd'
var treeViewVal = wndType.GetProperty("treeView", BindingFlags.NonPublic | BindingFlags.Instance).GetValue(wnd, null);
Debug.Log (treeViewVal + "\n"); // returns -> UnityEditor.TreeView
// Retrieves the property 'state' that is (public TreeViewState state { get; set; }) inside of 'treeViewVal'
var stateVal = treeViewVal.GetType().GetProperty("state").GetValue(treeViewVal, null);
Debug.Log (stateVal + "\n"); // returns UnityEditor.TreeViewState
// Retrive the value of the field 'scrollPos' (public Vector2 scrollPos;) inside of the 'stateVal'
var v2 = (Vector2)stateVal.GetType ().GetField ("scrollPos").GetValue (stateVal);
Debug.Log (v2 + "\n"); // returns -> (0.0, 0.0)
/// ALL OF THE ABOVE WORKS AS EXPECTED THE FOLLOWING IS WHERE IM STUMPED ///
// Retrieves the property 'gui' that is ( internal class GameObjectTreeViewGUI : TreeViewGUI) inside of 'treeViewVal'
var guiVal = treeViewVal.GetType().GetProperty("gui").GetValue(treeViewVal, null);
Debug.Log (guiVal + "\n"); // returns -> UnityEditor.GameObjectTreeViewGUI <- Type but I believe I need the Object
// THIS is where I'm stuck...
// Should retrieve the value of the field 'k_LineHeight' (protected float k_LineHeight = 16f;) inside of 'TreeViewGUI' the
var k_Line = guiVal.GetType().GetField ("k_LineHeight").GetValue (guiVal);
Debug.Log (k_Line + "\n"); // returns -> NullReferenceException: Object reference not set to an instance of an object
// If I attempt to ...
Type testType = guiVal.GetType ();
object test = Activator.CreateInstance(testType);
Debug.Log (test + "\n"); // returns -> Method not found: 'Default constructor not found...ctor() of UnityEditor.GameObjectTreeViewGUI'.
更新:
// ORIGINAL LINE
var k_LineA = guiVal.GetType().GetField ("k_LineHeight").GetValue(guiVal);
Debug.Log (k_LineA + "\n"); // returns-> Object reference not set to an instance of an object.
// SUGGESTED PART ONE
var k_LineB = guiVal.GetType().BaseType;
Debug.Log (k_LineB + "\n"); // returns -> UnityEditor.TreeViewGUI <- This is correct
// SUGGESTED PART TWO - > Have tried with an without various flags
var k_LineC = guiVal.GetType().BaseType.GetField("k_LineHeight", BindingFlags.Instance |
BindingFlags.Static |
BindingFlags.NonPublic |
BindingFlags.Public).GetValue(guiVal);
Debug.Log (k_LineC + "\n"); // returns -> Object reference not set to an instance of an object.
// GetValue wants guiVal to be an object???
// First part of UnityEditor.TreeViewGUI Class
namespace UnityEditor
{
internal abstract class TreeViewGUI : ITreeViewGUI
{
protected PingData m_Ping = new PingData();
private bool m_AnimateScrollBarOnExpandCollapse = true;
protected float k_LineHeight = 16f;
protected float k_BaseIndent = 2f;
protected float k_IndentWidth = 14f;
protected float k_FoldoutWidth = 12f;
protected float k_IconWidth = 16f;
protected float k_SpaceBetweenIconAndText = 2f;
protected float k_HalfDropBetweenHeight = 4f;
protected TreeView m_TreeView;
...
多虧您的建議,我現在才進入適當的班級。 覺得很傻,我沒想到這一點。 不幸的是,它在訪問期間仍然返回相同的值。 GetValue希望guiVal成為對象???
似乎越來越近,還有其他想法嗎?
您正在嘗試記錄對象而不是類型。類型是對象的屬性,定義對象是哪種類型,而對象是類
k_LineHeight
不在現場UnityEditor.GameObjectTreeViewGUI
。
GameObjectTreeViewGUI
繼承自TreeViewGUI
。 我用谷歌搜索,沒有找到源。 但是假設它是TreeViewGUI
一個字段,您可以執行
var k_Line = guiVal.GetType().BaseType.GetField ("k_LineHeight").GetValue (guiVal);
^^^
解答:我這邊的“更新”有錯字。 答案是,TheHenny和Scott的結合。 我試圖訪問僅在BaseType中可見的變量。 謝謝你倆!
最終代碼:
var k_LineC = guiVal.GetType().BaseType.GetField("k_LineHeight", BindingFlags.Instance |
BindingFlags.Static |
BindingFlags.NonPublic |
BindingFlags.Public).GetValue(guiVal);
Debug.Log (k_LineC + "\n"); // <-- returns 16
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.