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

我正在尝试使用一些固定字段来获取不安全结构的字段类型。 固定字段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+e__FixedBuffer0

Field3: System.UInt64


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

固定大小缓冲区的基础类型可以通过FixedBufferAttribute检索, 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() .Single() .ElementType; 

作为CodeInChaos,我也需要反映它,但我确实有FixedBufferAttribute

 [StructLayout(LayoutKind.Sequential, Pack=1)] public struct MyStruct { public uint Field1; [FixedBuffer(typeof(sbyte), 10)] public e__FixedBuffer0 Field2; public ulong Field3; // Nested Types [StructLayout(LayoutKind.Sequential, Size=10), CompilerGenerated, UnsafeValueType] public struct e__FixedBuffer0 { public sbyte FixedElementField; } } 

真棒的问题!

TestProjectNS.MyStruct+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的名称包含一些特殊字符,并且字段和嵌套类型都标记为安全关键字。

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