Type.GetFields()找不到Struct字段

时间:2014-09-13 21:07:47

标签: c# reflection

我使用Reflection中的以下行来获取对象中的所有字段:

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

它适用于我的所有领域,但完全忽略了这个:

private OffSet m_Offest;

'偏移'作为这样的结构:

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

此字段不在返回的数组中,有什么方法可以获取它吗?

以下是该类的定义。我在最后两个函数中得到了字段。

[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
}

2 个答案:

答案 0 :(得分:0)

正如我所料,问题在于继承。如果在基类中声明私有字段,则不返回它们。您需要使用Type.BaseType来获取该信息。

这是你如何做到的。

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();

答案 1 :(得分:-1)

我通过改变来自&#34; private&#34;的m_Offset的可访问性来解决了这个问题。到&#34;受保护&#34;。

问题是我从子类调用了GetFields()函数,而且这个类无法访问基类的私有字段。

我没有使用BaseType.GetFields()方法,因为我还需要获取子类的字段,而不仅仅是BaseType的字段。

感谢您的回答