Domanda

Sto cercando di ottenere le informazioni sul campo di un valore di matrice dall'interno di una struttura. Finora ho il seguente, ma non vedo come ottenere le informazioni che voglio.

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

Quindi se lo facessi:

 Type array_type = struct_field.FieldType.GetElementType();

Questo restituirebbe il tipo Test2, ma non voglio il tipo di array, voglio FieldInfo o Fields di quella struttura in modo da poter impostare i valori al suo interno.

È stato utile?

Soluzione

Ci scusiamo per la risposta iniziale errata. Ero troppo pigro per creare il mio tipo Test2, quindi ho usato una stringa. Ecco la risposta giusta (si spera):

Ho fatto quello che volevi fare con il seguente codice:

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

Questa è la linea più importante:

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

Dovrebbe darti il ??FieldInfo di cui stai parlando.

Altri suggerimenti

Cosa stai cercando esattamente? non è nessun FieldInfo per gli elementi nell'array ... puoi iterare i valori ottenendo l'array (come Array ) e ripetendolo ... basta usare:

Array arr = (Array)field.GetValue(obj);

Il problema con la tecnica di @ weiqure è che funziona solo se l'array contiene già almeno un elemento. Ecco un modo per trovare il tipo di elemento dell'array, che contenga o meno elementi:

bool GetArrayElementType(FieldInfo field, out Type elementType)
{
    if (field.FieldType.IsArray && field.FieldType.FullName.EndsWith("[]"))
    {
        string fullName = field.FieldType.FullName.Substring(0, field.FieldType.FullName.Length - 2);
        elementType = Type.GetType(string.Format("{0},{1}", fullName, field.FieldType.Assembly.GetName().Name));
        return true;
    }
    elementType = null;
    return false;
}

Ed ecco come useresti quella funzione:

void Test(object targetObject, string fieldName)
{
    FieldInfo field = targetObject.GetType().GetField(fieldName);
    Type elementType;
    bool success = GetArrayElementType(field, out elementType);
}
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top