2016-07-02 12 views
0

Ich bin nicht neu in OOP, aber bin neu in Reflection. Ich bin mir sicher, dass ich etwas Einfaches verpasse und seit einiger Zeit experimentiere, bevor ich posten kann.Reflection C# - Wie man Griff zu Klasse mehrere Eigenschaften tief

Ich habe versucht, Zugriff auf ein Feld zu bekommen, sowohl zu bekommen und zu setzen, seinen Wert. Das Problem ist, dass das Feld innerhalb der Eigenschaft einer Klasse innerhalb einer Eigenschaft einer Klasse liegt.

Der folgende Code ruft ein vorhandenes Fenster auf und arbeitet tiefer in die Klassen, bis ich auf eine Wand stoße. Letztendlich möchte ich "k_LineHeight" innerhalb einer vorhandenen Instanz von TreeViewGUI abrufen und setzen.

Der folgende Code ist stark annotiert. Danke, dass Sie sich die Zeit genommen haben, sich das anzusehen. In Unity Mono Debug.Log() ist das Äquivalent von Schreiben in die Konsole.

// 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'. 

UPDATE:

// 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; 
       ... 

Dank Ihren Vorschlag Ich bin jetzt in die richtige Klasse. Fühle mich dumm, daran habe ich nicht gedacht. Leider ist es beim Zugriff immer noch gleich. GetValue möchte, dass guiVal ein Objekt ist ???

Scheint näher, hat jemand zusätzliche Gedanken?

+0

Um nicht öffentliche Mitglieder erhalten sollten Sie die Überlastung, die Sie Binding angeben kann. Dann verwenden Sie 'BindingFlags.NonPublic' zusammen mit' Instance' oder 'Static'. – thehennyy

Antwort

0

Sie versuchen, ein Objekt und nicht eine Art einzuloggen .. Typ ist ein Attribut eines Objekts zu definieren, welche Art von Typ das Objekt, während Objekt der Klasse in UnityEditor.GameObjectTreeViewGUI

0

ANTWORT tun könnte: Die „Update“ auf meiner Seite war ein Tippfehler. Die Antwort darauf ist die Kombination von TheHenny's und Scott's. Ich habe versucht, auf eine Variable zuzugreifen, die nur im BaseType sichtbar ist. Danke euch beiden!

Schlusscode:

 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