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+
是嵌套类型。 它包含您想要的基础类型的单个字段。
因此,给定固定大小数组的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"; } }