0

I got an issue.

In Unity I want to reflect into a private field. But I always get null for the fieldinfo. what am I doing wrong?

public abstract class _SerializableType
{
    [SerializeField] private string name;
}

// because I am using a CustomPropertyDrawer for all inherited from _SerializeType
public class SerializableType<T> : _SerializableType { }
public class SerializableType : _SerializableType { }

[Serializable] public class CTech : SerializableType<_CouplingTechnology> { }

so using this method should actually work.

        // type is CTech
        // propertyPath in that case is "name"
        FieldInfo info = type.GetField(propertyPath, BindingFlags.Instance
                         | BindingFlags.Public | BindingFlags.NonPublic);

What am I doing wrong?

I am calling this method in a managed library that has its own CustomInspector. so it reflects into every field and figure how to display it. AppDomain is fullyTrusted. I don't know what else could be of importance...

Christoph Wolf
  • 95
  • 1
  • 12
  • 6
    variable `type` is `typeof(_SerializableType)` ? – Anton Komyshan Dec 28 '17 at 13:44
  • 1
    In addition to what @AntonKomyshan said, the variable `propertyPath` should also be the string "name"? – Steve Danner Dec 28 '17 at 13:47
  • @AntonKomyshan yep type is of _SerializeType ( got through the Iterator of seriliazedObject) told you it's more complicated ;-) SteveDanner I put than in... – Christoph Wolf Dec 28 '17 at 13:50
  • 4
    What is `type` here? If it's not `_SerializableType` then you will not be able to see the private field, even the derived class isn't aware of it. – DavidG Dec 28 '17 at 13:51
  • it actually is part of [Serializable] public class CTech : SerializableType<_CouplingTechnology> { } because unity's serialization is damn shallow. how about the subclass? – Christoph Wolf Dec 28 '17 at 13:53
  • 2
    The comments shows that you need to post some more code. Show how `type` is declared. Also, hardcode "name" to `propertyPath` and see what happens – Programmer Dec 28 '17 at 13:54
  • type actually is Type type = GetEligibleObjectType(property.serializedObject, parentPath); told you it gets complicated. And i'm printing it's full name, which tells me it is a CTech – Christoph Wolf Dec 28 '17 at 13:58
  • 2
    Like I said, a derived class doesn't have a private field from a base class. – DavidG Dec 28 '17 at 14:00
  • You replied to @AntonKomyshan 's comment wit yes which is actually false. – Programmer Dec 28 '17 at 14:04
  • @Programmer, yeah, so implicit conversion doesn't work here you say? – Christoph Wolf Dec 28 '17 at 14:06
  • @DavidG so, how am I going to get a private field that is inherited from another class? – Christoph Wolf Dec 28 '17 at 14:08
  • 3
    You need to show us how you're getting `type`. Saying it's complicated doesn't help us help you. It does the opposite. We need a [mcve] –  Dec 28 '17 at 14:10

2 Answers2

10

The only way to get a private field that is declared in a base class from a derived type is to go up the class hierarchy. So for example, you could do something like this:

public FieldInfo GetPrivateFieldRecursive(Type type, string fieldName)
{
    FieldInfo field = null;

    do
    {
        field = type.GetField(fieldName, BindingFlags.Instance | BindingFlags.Public 
            | BindingFlags.NonPublic | BindingFlags.GetField);
        type = type.BaseType;

    } while(field == null && type != null);

    return field;
}
DavidG
  • 113,891
  • 12
  • 217
  • 223
3

You have to ensure that your object is actually of the desired type and then call GetField on the right type object.

using System;
using System.Reflection;

public class Program
{
    public static void Main()
    {
        var obj = new SerializableType();
        // reflection version of "obj is _SerializableType":
        if(typeof(_SerializableType).IsAssignableFrom(obj.GetType()))
        {
            var info = typeof(_SerializableType).GetField("name", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
            var name = info.GetValue(obj);
            Console.WriteLine(name);
        }

    }
}

public abstract class _SerializableType
{
    public string name = "xyz";
}

public class SerializableType : _SerializableType { }
thehennyy
  • 4,020
  • 1
  • 22
  • 31
  • hey champ, thanks for the answer. But i need seomthing more flexible, like @DavidG s answer. because of: _I am calling this method in a managed library that has its own CustomInspector. so it reflects into every field and figure how to display it._ – Christoph Wolf Dec 28 '17 at 14:33