-1

I am using the following line from Reflection to get all the fields in my object:

FieldInfo[] l_Fields = GetType().GetFields( BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance );

It works fine for all my fields but ignores this one completely:

private OffSet m_Offest;

'Offset' being a struct made as such:

public struct OffSet
{
  public float x;
  public float y;
}

This field is not in the returned array, is there any way to get it?

Here is the definition of the class. I am getting the fields in the last two functions.

[Serializable]
public abstract class AITreeNode : ISerializable
{
    //>----------------------------------------------------------------------------------------
    // STRUCT
    //-----------------------------------------------------------------------------------------

    public struct OffSet
    {
        public float x;
        public float y;
    }

    //>----------------------------------------------------------------------------------------
    // ENUM
    //-----------------------------------------------------------------------------------------
    public enum Status
    {
        None,
        Available,
        Unavailable,
        Active,
        Success,
        Failed
    }
    //>-----------------------------------------------------------------------------------------
    // VARIABLES
    //------------------------------------------------------------------------------------------
    public      String          Caption;
    public      bool            Enabled                 = true;
    // Display
    private     OffSet          m_Offest;

    // Non Serialized data
    [NonSerialized] protected   AITree          m_AITreeAT;
    [NonSerialized] protected   AITreeBranch    m_BranchATB;
    [NonSerialized] protected   Status          m_LastStatusS = Status.None;
    [NonSerialized] protected   bool            m_IsActiveB;

    //>-----------------------------------------------------------------------------------------
    // GETTERS
    //------------------------------------------------------------------------------------------
    public AITreeBranch     GetBranchATB()      {       return m_BranchATB;     }
    public bool             IsActive()          {       return m_IsActiveB;     }
    public Status           LastStatusS()       {       return m_LastStatusS;     }
    //>-----------------------------------------------------------------------------------------
    // SETTERS
    //------------------------------------------------------------------------------------------
    public void             SetBranch   ( AITreeBranch _BranchATB   )   {   m_BranchATB = _BranchATB;   }
    public void             SetAITree   ( AITree _TreeAT            )   {   m_AITreeAT = _TreeAT;       }
    //>-----------------------------------------------------------------------------------------
    //-----------------------------------------------------------------------------------------
    public float X
    {            get { return m_Offest.x; }             set { m_Offest.x = value; }                 }
    //>-----------------------------------------------------------------------------------------
    public float Y
    {            get { return m_Offest.y; }             set { m_Offest.y = value;  }                }
    //>-----------------------------------------------------------------------------------------

    //>-----------------------------------------------------------------------------------------
    //------------------------------------------------------------------------------------------
    public AITreeNode()
    {
        m_Offest.y = -5;
    }

    #region Serialization
    //>-----------------------------------------------------------------------------------------
    // The special constructor is used to deserialize values.
    // Every class inheriting from AITreeNode needs to implement a constructor with such parameters
    //------------------------------------------------------------------------------------------
    public AITreeNode( SerializationInfo info, StreamingContext context )
    {
        // Reset the property value using the GetValue method.
        FieldInfo[] l_FieldsAFI = GetType().GetFields( BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance );
        foreach ( FieldInfo fieldInfo in l_FieldsAFI )
        {
            if ( fieldInfo.IsNotSerialized ) continue;
            try
            {
                fieldInfo.SetValue( this, info.GetValue( fieldInfo.Name, fieldInfo.FieldType ) );
            }
            catch
            {
                UnityEngine.Debug.Log( "Field " + fieldInfo.Name + " is new. Default value is used" );
            }
        }
    }
    //>-----------------------------------------------------------------------------------------
    // Implement this method to serialize data. The method is called on serialization.
    //------------------------------------------------------------------------------------------
    public void GetObjectData(SerializationInfo info, StreamingContext context)
    {
        // Use the AddValue method to specify serialized values.
        FieldInfo[] l_FieldsAFI = GetType().GetFields( BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance );

        foreach ( FieldInfo fieldInfo in l_FieldsAFI )
        {
            if ( fieldInfo.IsNotSerialized )
            {                    
                UnityEngine.Debug.Log( "Non serialized Field " + fieldInfo.Name );
                continue;
            }
            info.AddValue( fieldInfo.Name, fieldInfo.GetValue( this ), fieldInfo.FieldType );


        UnityEngine.Debug.Log( "Saving Field " + fieldInfo.Name );
            }
        }
... rest of the class
}
Claus Jørgensen
  • 25,882
  • 9
  • 87
  • 150
Ryan Pergent
  • 4,432
  • 3
  • 36
  • 78
  • 1
    What is the type you're trying to get the fields from ? Post that type definition. – Sriram Sakthivel Sep 13 '14 at 21:13
  • I'm a trying to get the fields from a custom class... It's a bit big to put it completely here. This class contains several fields of all kind of types (float, int, etc, and other custom classes). All these fields are returned in the Array, except my field m_Offset. What kind of info do you need? – Ryan Pergent Sep 13 '14 at 21:21
  • Is this by any chance the only private field? – nphx Sep 13 '14 at 21:21
  • 2
    Post some field for which it returns FieldInfo and your Offest field for which it doesn't. Do both of them exist in same class or you have inheritance? A short but complete program will be very helpful for us. – Sriram Sakthivel Sep 13 '14 at 21:23
  • @SriramSakthivel I've deleted my answer because I feel that it was an actual answer that won't be understood as an answer, even when *giving a confirmation to OP* is still an actual answer. – Matías Fidemraizer Sep 13 '14 at 21:30
  • @MatíasFidemraizer Your answer is very true, at first sight itself I know that this code should work, but that doesn't help to resolve OP's problem. Does that? Atleast if you have guided op about what could have gone wrong, it is a valid answer, but your answer doesn't. – Sriram Sakthivel Sep 13 '14 at 21:32
  • 1
    @MatíasFidemraizer You basically said 'Yes, you are doing something wrong.' How is that a helpful answer? – nphx Sep 13 '14 at 21:32
  • @SriramSakthivel I said, I tested your code and it works, there's something outside the scope of the current question that prevents your code from working. The issue isn't with the reflection approach itself, but some other issue. Posted code ir correct <--- this was the answer. – Matías Fidemraizer Sep 13 '14 at 21:39
  • @nphx It was helpful because OP would get some guidance in that the issue isn't the posted code. – Matías Fidemraizer Sep 13 '14 at 21:40
  • @nphx I took my time to copy-pasting the whole code in DotNetFiddle, adding a test class with an `OffSet`-typed field, checking if the issue was there and confirming OP and myself that the code should work. But ok, it was an useless effort. – Matías Fidemraizer Sep 13 '14 at 21:41
  • @MatíasFidemraizer IMO that should be a comment optionally linking to working fiddle program. That is not an answer to question what I am doing wrong? If there is not enough information to answer, request clarification or you may go harsh and close the question saying *Why my code doesn't work kind of questions should post the code to reproduce...* – Sriram Sakthivel Sep 13 '14 at 21:43
  • @SriramSakthivel Answers are editable. It wouldn't be the first time I post an initial answer, OP gives me more info, and our collaboration ends in 1, 3 or 3 updates to the answer – Matías Fidemraizer Sep 13 '14 at 21:44
  • @SriramSakthivel I believe that sometimes you and others take this so seriously, when there're vocational people like me that come here to assist others in their issues rather than hunting reputation. I mean that "no, it works" it's also an answer, and this is irrefutable. And maybe the OP looks at such simple answer and says "ok, I'll investigate another part of my code" and OP provides more detail when he/she realizes that the issue wasn't in the code that was originally posted. – Matías Fidemraizer Sep 13 '14 at 21:47
  • [That's why comments exist](http://meta.stackoverflow.com/questions/266426/is-it-ok-to-answer-vague-unclear-questions). Answers should be answers, hey it works for me is not an answer is my point. Cast a close vote saying can't reproduce or whatever relevant. That's why they exist. – Sriram Sakthivel Sep 13 '14 at 21:52
  • @SriramSakthivel If provided code works and OP says it won't work, but it works, a demonstration that it works can be work as a guidance to solve the underlying issue. I've been posting in SO for a long time and I both use comments and answers, and this time I felt that an answer saying "you're wrong, it works" should work as an actual answer. – Matías Fidemraizer Sep 13 '14 at 21:54
  • I added more details to my question. – Ryan Pergent Sep 13 '14 at 21:55
  • @MatíasFidemraizer If you're interested which is the right way you may raise a question in meta.stackoverflow. Discussing here is just makeing noise, adds nothing to this question. – Sriram Sakthivel Sep 13 '14 at 21:58
  • @SriramSakthivel Absolutely, BTW, you take this too seriously. – Matías Fidemraizer Sep 13 '14 at 21:59
  • This question is a possible duplicate of http://stackoverflow.com/questions/6961781/reflecting-a-private-field-from-a-base-class . As I retracted a previous close vote, I can't vote to close because of question duplicity. – Matías Fidemraizer Sep 13 '14 at 22:00

2 Answers2

1

As I anticipated, the issue is with inheritance. Private fields are not returned if it was declared in base class. You need to use Type.BaseType to get that info.

Here's how you do it.

var typeHierarchies = new List<Type>();
var type = this.GetType();      
while(type.BaseType != null)
{
    typeHierarchies.Add(type);
    type = type.BaseType;
}
FieldInfo[] l_Fields = typeHierarchies.SelectMany( x=>x.GetFields( BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance)).ToArray();
Sriram Sakthivel
  • 72,067
  • 7
  • 111
  • 189
-1

I solved the problem by changing the accessibility of m_Offset from "private" to "protected".

The issue was that I was calling the GetFields() function from a child class and this class couldn't access the private fields of the base.

I didn't go with the BaseType.GetFields() method because I also needed to get the fields of the subclass , not only those of the BaseType.

Thank you for the answers

Ryan Pergent
  • 4,432
  • 3
  • 36
  • 78
  • 1
    I am not sure I understand how things work here... Why do I get downvoted twice when I actually post the solution to my problem? Even my question itself got downvoted. Is my mistake to have actually ask a question without knowing the cause of the problem before? – Ryan Pergent Sep 13 '14 at 22:18