Search code examples
c#reflectionstructfieldinfo

How do I get the FieldInfo of an array field?


I'm trying to get the field info of an array value from within a struct. So far I have the following, but I dont see how to get the infomration I want.

    [StructLayout(LayoutKind.Sequential)]
    public struct Test
    {
        public byte Byte1;
        [MarshalAs(UnmanagedType.ByValArray, SizeConst=3)]
        public Test2[] Test1;
    }

    BindingFlags struct_field_flags = BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Static | BindingFlags.Instance | BindingFlags.DeclaredOnly;
    FieldInfo[] all_struct_fields = typeof(Test).GetFields(struct_field_flags);
    foreach (FieldInfo struct_field in all_struct_fields)
    {
        if(struct_field.FieldType.IsArray)
        {
           // Get FieldInfo for each value in the Test1 array within Test structure
        }
    }

So if I did:

 Type array_type = struct_field.FieldType.GetElementType();

This would return Test2 type, but I dont want the type of the array, I want the FieldInfo or Fields of that structure so I can set values from within it.


Solution

  • Sorry for the initial wrong answer. I was too lazy to create my own Test2 type so I used a string instead. Here's the right answer (hopefully):

    I did what you want to do with the following code:

    class Program
    {
        static void Main(string[] args)
        {
            object sampleObject = GetSampleObject();
            FieldInfo[] testStructFields = typeof(Test).GetFields();
    
            foreach (FieldInfo testStructField in testStructFields)
            {
                if (testStructField.FieldType.IsArray)
                {
                    // We can cast to ILIst because arrays implement it and we verfied that it is an array in the if statement
                    System.Collections.IList sampleObject_test1 = (System.Collections.IList)testStructField.GetValue(sampleObject);
                    // We can now get the first element of the array of Test2s:
                    object sampleObject_test1_Element0 = sampleObject_test1[0];
    
                    // I hope this the FieldInfo that you want to get:
                    FieldInfo myValueFieldInfo = sampleObject_test1_Element0.GetType().GetField("MyValue");
    
                    // Now it is possible to read and write values
                    object sampleObject_test1_Element0_MyValue = myValueFieldInfo.GetValue(sampleObject_test1_Element0);
                    Console.WriteLine(sampleObject_test1_Element0_MyValue); // prints 99
                    myValueFieldInfo.SetValue(sampleObject_test1_Element0, 55);
                    sampleObject_test1_Element0_MyValue = myValueFieldInfo.GetValue(sampleObject_test1_Element0);
                    Console.WriteLine(sampleObject_test1_Element0_MyValue); // prints 55
                }
            }
        }
    
        static object GetSampleObject()
        {
            Test sampleTest = new Test();
            sampleTest.Test1 = new Test2[5];
            sampleTest.Test1[0] = new Test2() { MyValue = 99 };
            object sampleObject = sampleTest;
            return sampleObject;
        }
    }
    
    [StructLayout(LayoutKind.Sequential)]
    public struct Test2
    {
        public int MyValue;
    }
    
    [StructLayout(LayoutKind.Sequential)]
    public struct Test
    {
        public byte Byte1;
        [MarshalAs(UnmanagedType.ByValArray, SizeConst = 3)]
        public Test2[] Test1;
    }
    

    This is the most important line:

    FieldInfo myValueFieldInfo = sampleObject_test1_Element0.GetType().GetField("MyValue");
    

    It should give you the FieldInfo that you are talking about.