簡體   English   中英

反射C#-如何獲取對幾個屬性進行深入分類的句柄

[英]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

https://github.com/MattRix/UnityDecompiled/blob/master/UnityEditor/UnityEditor/GameObjectTreeViewGUI.cs

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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM