Question

J'essaie d'obtenir les informations de champ d'une valeur de tableau à l'intérieur d'une structure. Jusqu'à présent, j'ai les informations suivantes, mais je ne vois pas comment obtenir les informations souhaitées.

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

Donc si je le faisais:

 Type array_type = struct_field.FieldType.GetElementType();

Ceci renverrait le type Test2, mais je ne veux pas le type du tableau, je veux le FieldInfo ou les champs de cette structure pour pouvoir définir des valeurs à partir de celui-ci.

Était-ce utile?

La solution

Désolé pour la mauvaise réponse initiale. J'étais trop paresseux pour créer mon propre type Test2 et j'ai donc utilisé une chaîne. Voici la bonne réponse (espérons-le):

J'ai fait ce que vous voulez faire avec le code suivant:

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

C’est la ligne la plus importante:

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

Cela devrait vous donner le FieldInfo dont vous parlez.

Autres conseils

Qu'est-ce que vous cherchez exactement? Il n'existe pas FieldInfo pour les éléments du tableau ... vous pouvez itérer les valeurs en récupérant le tableau (sous la forme Array ) et en le réitérant. ... utilisez simplement:

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

Le problème avec la technique de @ weiqure est que cela ne fonctionne que si le tableau contient déjà au moins un élément. Voici un moyen de trouver le type d'élément du tableau, qu'il contienne ou non des éléments:

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

Et voici comment vous utiliseriez cette fonction:

void Test(object targetObject, string fieldName)
{
    FieldInfo field = targetObject.GetType().GetField(fieldName);
    Type elementType;
    bool success = GetArrayElementType(field, out elementType);
}
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top