2009-08-03 1 views
3

私は構造体の中から配列値のフィールド情報を取得しようとしています。これまでのところ、私は次のことを持っていますが、私が望む情報を得る方法は分かりません。配列フィールドのFieldInfoを取得するにはどうすればよいですか?

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

私がやったのであれば:

Type array_type = struct_field.FieldType.GetElementType(); 

これはTest2を型を返すだろうが、私は配列の型をたくない、私はのFieldInfoまたはその構造体のフィールドは、私からの値を設定することができますしたいですその中で。

答えて

3

初期間違った答えのために申し訳ありません。私は自分のTest2タイプを作成するには怠惰でしたので、代わりに文字列を使用しました。ここでは、正しい答えは(たぶん)です:

私はあなたが次のコードで何をしたいかをやった:

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

これが最も重要なラインです:

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

それはあなたを与える必要がありますあなたが話しているFieldInfo。

3

あなたは正確に何をしていますか?そこだけで使用... ...あなたが(Arrayとして)配列を取得し、それを繰り返すことで値を繰り返すことができ、アレイ内の項目のFieldInfoではありません:

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

私はTest2をするのFieldInfoを取得したいと思います私はその構造内から値を設定することができます – SwDevMan81

+0

Test1はい、私はTest2の配列のためにそれをします。それが配列の場合は、配列型のFieldInfoを取得して、Test1値のfield.SetValue(obj、value)を実行できるようにしたいと考えています。 – SwDevMan81

+0

あなたはTest1とTest2の間のどこかで私を失ってしまいました...もしあなたが配列の中の各インスタンスを意味するならば、それぞれのインスタンスをオブジェクトとして扱います...次にGetType()などがあります。あるいはarr.GetType()を使います。 ()。しかし、配列の内側に*を指すフィールドはありません。 –

0

@ weiqureの手法の問題点は、配列にすでに少なくとも1つの要素がある場合にのみ機能することです。ここでは、要素が含まれているかどうか、配列の要素の型を見つけるための方法です:

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

そして、ここでは、あなたがその機能を使用する方法である:

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

実際には、この部分は不要です: '&& field.FieldType.FullName.EndsWith(" [] ")' ...しかし、私は完全性のために追加すると思っていました。 –