如何从.NET Core中的类型中获取特定属性的封送大小
本文关键字:属性 类型 NET Core 获取 | 更新日期: 2023-09-27 17:58:01
在.NET Core中,只有一个通用方法Marshal.SizeOf<T>()
可用(Marshal.SizeOf(Type t)
已弃用)。但我想列举一个类的所有属性,并得到它们的封送大小。我该怎么办?
这是我的代码:(实际上不是我的,而是我试图移植到.NET Core的代码)
来自https://github.com/kapetan/dns/blob/master/DNS/Protocol/Marshalling/Struct.cs修改
private static byte[] ConvertEndian<T>(byte[] data)
{
var fields = typeof(T).GetRuntimeFields().Where(f => f.IsStatic == false);
EndianAttribute endian = typeof(T).GetTypeInfo().GetCustomAttribute<EndianAttribute>();
foreach (FieldInfo field in fields)
{
if (endian == null && field.GetCustomAttribute<EndianAttribute>(false) == null)
{
continue;
}
int offset = Marshal.OffsetOf<T>(field.Name).ToInt32();
// *** This is deprecated ***
// int length = Marshal.SizeOf(field.FieldType);
// *** This doesn't work at all ***
int length = field.FieldType.GetTypeInfo().StructLayoutAttribute.Size;
endian = endian ?? field.GetCustomAttribute<EndianAttribute>(false);
if (endian.Endianness == Endianness.Big && BitConverter.IsLittleEndian ||
endian.Endianness == Endianness.Little && !BitConverter.IsLittleEndian)
{
Array.Reverse(data, offset, length);
}
}
return data;
}
您需要的是决定在运行时应该使用什么泛型类型。确实有一种方法可以做到这一点:动态类型
C#参考说,
动态类型使其发生的操作能够绕过编译时类型检查。相反,这些操作在运行时解决。
所以你可以定义一个方法:
static int GetLength<T>(T obj)
{
return Marshal.SizeOf<T>();
}
然后通过反射创建一个类型为T
的动态实例:
dynamic obj = Activator.CreateInstance(field.FieldType.GetTypeInfo());
int length = GetLength(obj);
运行时将为该方法选择合适的类型参数T。
此解决方案有一个限制,即不能创建没有默认构造函数的类型的实例。您可以定义一个没有实际字段的包装类Wrapper<T>
,并将其创建为运行时,以确保构造函数能够工作。但我不知道它是否有效。