[英]Reflection C# - How to get handle to class several properties deep
I am not new to OOP, but am new to Reflection. 我不是OOP的新手,而是反射的新手。 I'm sure I'm missing something simple and have experimented for some time before posting. 我确定我错过了一些简单的东西,并且在发布之前已经尝试了一段时间。
I have been trying to get access to a field, both get and set, its value. 我一直试图获取对字段的访问,包括获取和设置其值。 The issue is the field is within property of a class within a property of a class. 问题是该字段位于类的属性内。
The following code gets an existing window and works deeper into the classes until I hit a wall. 以下代码获取了一个现有窗口,并在类中进行了更深入的研究,直到碰壁。 Ultimately I want to get and set "k_LineHeight" inside of an existing instance of TreeViewGUI. 最终,我想在TreeViewGUI的现有实例中获取并设置“ k_LineHeight”。
The following code is heavily annotated. 以下代码带有大量注释。 Thank you for taking the time to look at this. 感谢您抽出宝贵的时间对此进行研究。 In Unity's Mono Debug.Log() is the equivalent of write to the console. 在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'.
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;
...
Thanks to your suggestion I am now into the proper class. 多亏您的建议,我现在才进入适当的班级。 Feel silly I didn't think of that. 觉得很傻,我没想到这一点。 Unfortunately its still returning the same during access. 不幸的是,它在访问期间仍然返回相同的值。 GetValue wants guiVal to be an object??? GetValue希望guiVal成为对象???
Seems closer, anyone have additional thoughts? 似乎越来越近,还有其他想法吗?
您正在尝试记录对象而不是类型。类型是对象的属性,定义对象是哪种类型,而对象是类
k_LineHeight
isn't a field in UnityEditor.GameObjectTreeViewGUI
. k_LineHeight
不在现场UnityEditor.GameObjectTreeViewGUI
。
https://github.com/MattRix/UnityDecompiled/blob/master/UnityEditor/UnityEditor/GameObjectTreeViewGUI.cs https://github.com/MattRix/UnityDecompiled/blob/master/UnityEditor/UnityEditor/GameObjectTreeViewGUI.cs
GameObjectTreeViewGUI
inherits from TreeViewGUI
. GameObjectTreeViewGUI
继承自TreeViewGUI
。 I googled and didn't find the source for that. 我用谷歌搜索,没有找到源。 But assuming that it is a field in TreeViewGUI
you could do 但是假设它是TreeViewGUI
一个字段,您可以执行
var k_Line = guiVal.GetType().BaseType.GetField ("k_LineHeight").GetValue (guiVal);
^^^
ANSWER : The "Update" on my side had a typo. 解答:我这边的“更新”有错字。 The answer to this is the one is a combination of both TheHenny's and Scott's. 答案是,TheHenny和Scott的结合。 I was attempting to access a variable only visible in the BaseType. 我试图访问仅在BaseType中可见的变量。 Thank you both! 谢谢你俩!
Final code: 最终代码:
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.