简体   繁体   English

反射C#-如何获取对几个属性进行深入分类的句柄

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

相关问题 c# 反射,如何获得泛型类型 class 属性 - c# Reflection, how to get generic type class properties 如何使用C#反射获取实例化的属性或不为null的类类型的属性 - How to use C# reflection to get properties that are instantiated or properties of a class type that are not null C#反思:如何从基类获取派生类的属性 - C# Reflection: How to get the properties of the derived class from the base class 使用C#反射从类T获取属性列表 - Get List of Properties from a Class T using C# Reflection 使用反射在运行时C#获取类实例的属性 - Using reflection to get properties of an instance of a class at runtime C# c#如何通过反射获取派生类属性列表,先按基类属性排序,然后派生类props - c# how to get list of derived class properties by reflection, ordered by base class properties first, and then derived class props 您如何使用反射获得一个类及其基类(在层次结构中)的所有属性? (C#) - How do you get the all properties of a class and its base classes (up the hierarchy) with Reflection? (C#) 通用 C# - 如何使用反射将属性分配给通用 class - Generic C# - how to use reflection to assign properties to generic class 在C#中标记类的属性以进行反射 - Mark properties of class for reflection in C# 获取C#反射中的属性类型 - get type of properties in C# reflection
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM