C#使用反射获取不安全结构中的固定字段类型

时间:2011-03-23 18:43:00

标签: c# reflection unsafe

我正在尝试使用一些固定字段来获取不安全结构的字段类型。固定字段FieldType不返回实际类型。

[StructLayout(LayoutKind.Sequential, Pack = 1)]
public unsafe struct MyStruct
{
   public UInt32 Field1;
   public fixed sbyte Field2[10];
   public UInt64 Field3;
}

void Test() 
{
   var theStruct = new MyStruct();
   string output = "";
   foreach (FieldInfo fi in theStruct.GetType().GetFields(BindingFlags.Public | BindingFlags.Instance))
   {
      output += fi.Name + ": " + fi.FieldType.ToString() + "\r\n";
   }

}

输出:

Field1:System.UInt32

Field2:TestProjectNS.MyStruct+<Field2>e__FixedBuffer0

Field3:System.UInt64


我正在寻找Field2告诉我sbyte而不是TestProjectNS.MyStruct+<Field2>e__FixedBuffer0

3 个答案:

答案 0 :(得分:6)

固定大小缓冲区的基础类型可以通过FixedBufferAttribute检索,foreach (FieldInfo fi in typeof(MyStruct).GetFields(BindingFlags.Public | BindingFlags.Instance)) { var attr = fi.GetCustomAttributes(typeof(FixedBufferAttribute), false); if(attr.Length > 0) output += fi.Name + ": " + ((FixedBufferAttribute)attr[0]).ElementType + "\r\n"; else output += fi.Name + ": " + fi.FieldType + "\r\n"; } 应用于固定大小的缓冲区语句。

var type = typeof (MyStruct)
            .GetField("Field2")
            .GetCustomAttributes(typeof (FixedBufferAttribute), false)
            .Cast<FixedBufferAttribute>()
            .Single()
            .ElementType;

或单字段短版本:

FixedBufferAttribute

作为CodeInChaos,我还需要反映它,但我确实有[StructLayout(LayoutKind.Sequential, Pack=1)] public struct MyStruct { public uint Field1; [FixedBuffer(typeof(sbyte), 10)] public <Field2>e__FixedBuffer0 Field2; public ulong Field3; // Nested Types [StructLayout(LayoutKind.Sequential, Size=10), CompilerGenerated, UnsafeValueType] public struct <Field2>e__FixedBuffer0 { public sbyte FixedElementField; } }

{{1}}

很棒的问题!

答案 1 :(得分:4)

TestProjectNS.MyStruct+<Field2>e__FixedBuffer0是嵌套类型。它包含您想要的基础类型的单个字段。

因此,给定固定大小数组的FieldInfo,您可以这样做:

Type bufferFieldType=fixedBufferFieldInfo.FieldType.GetFields(BindingFlags.Public | BindingFlags.Instance).Single().FieldType;

C#编译器生成的内容类似于以下内容:

[StructLayout(LayoutKind.Sequential, Pack = 1)]
public unsafe struct MyStruct
{
   [StructLayout(LayoutKind.Sequential, Pack = 1, Size=10)]
   public struct Field2e__FixedBuffer0
    {
        public sbyte FixedElementField;
    }
   public UInt32 Field1;
   public Field2e__FixedBuffer0 Field2;
   public UInt64 Field3;
}

除了生成的struct的名称包含一些特殊字符,并且字段和嵌套类型都标记为安全关键字。

答案 2 :(得分:-1)

CodeInChaos是对的。另一种方法可以做到:

foreach (FieldInfo fi in theStruct.GetType().GetFields(BindingFlags.Public | BindingFlags.Instance))
{
   if (fi.FieldType.IsNested)
   {
      output += fi.Name + ": " + 
          fi.FieldType.GetFields()[0].FieldType.ToString() + "\r\n";
   }
   else
   {
      output += fi.Name + ": " + fi.FieldType.ToString() + "\r\n";
   }
}