2009-08-03 15 views
3

Ich versuche, die Feldinformationen eines Array-Werts aus einer Struktur zu erhalten. Bis jetzt habe ich folgendes, aber ich sehe nicht, wie ich die Information bekommen kann, die ich will.Wie bekomme ich die FieldInfo eines Arrayfeldes?

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

Also, wenn ich tat:

Type array_type = struct_field.FieldType.GetElementType(); 

Dies würde Test2 Typ zurückgeben, aber ich nicht den Typ des Arrays, ich will die Fieldinfo oder Felder dieser Struktur, so kann ich Werte von darin.

Antwort

3

Sorry für die anfängliche falsche Antwort . Ich war zu faul, um meinen eigenen Test2-Typ zu erstellen, also benutzte ich stattdessen eine Zeichenkette. Hier ist die richtige Antwort (hoffentlich):

Ich tat, was Sie mit dem folgenden Code zu tun:

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

Dies ist die wichtigste Zeile:

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

Es sollte Ihnen die FieldInfo, von der du sprichst.

3

Wonach genau suchen Sie? Es ist keine FieldInfo für die Elemente im Array ... Sie die Werte, indem man das Array (wie Array) laufen kann und es iterieren ... benutzen Sie einfach:

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

würde Ich mag die Fieldinfo von Test2 bekommen so dass ich Werte innerhalb dieser Struktur setzen konnte – SwDevMan81

+0

Für Test1 ja, aber ich will es für das Array von Test2's. Wenn es ein Array ist, möchte ich die FieldInfo des Array-Typs erhalten, so dass ich field.SetValue (obj, value) für den Test1-Wert tun kann. – SwDevMan81

+0

Sie haben mich irgendwo zwischen Test1 und Test2 verloren ... wenn Sie jede Instanz innerhalb des Arrays meinen, dann behandeln Sie jede Instanz als ein Objekt ... dann haben Sie GetType() usw. Oder verwenden Sie arr.GetType(). GetElementType(). Aber es gibt kein Feld, das * innerhalb * des Arrays zeigt. –

0

Das Problem mit @ Weiqure Technik ist, dass es nur funktioniert, wenn das Array bereits mindestens ein Element enthält. Hier ist ein Weg des Arrays Elementtyp zu finden, ob es Elemente enthält oder nicht:

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

Und hier ist, wie Sie diese Funktion verwenden würden:

void Test(object targetObject, string fieldName) 
{ 
    FieldInfo field = targetObject.GetType().GetField(fieldName); 
    Type elementType; 
    bool success = GetArrayElementType(field, out elementType); 
} 
+0

Eigentlich ist dieser Teil unnötig: '&& field.FieldType.FullName.Endswith (" [] ")' ... aber ich dachte, ich würde es der Vollständigkeit halber hinzufügen. –