【问题标题】:How do I get marshal size of a specific property from a type in .NET Core?如何从 .NET Core 中的类型获取特定属性的编组大小?
【发布时间】:2016-07-21 15:35:45
【问题描述】:

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

【问题讨论】:

  • 您不应该编写这样的代码,它从根本上与提前编译(又名 .NET Native)不兼容。这在 .NETCore 中非常重要,数百个小程序集完全杀死了冷启动时间。不是说你不能这样做,BinaryReader 还可以让你读取网络数据包。

标签: c# .net .net-core


【解决方案1】:

您需要决定在运行时应该使用哪种泛型类型。确实有一种方法可以做到这一点:dynamic 类型。
C# Reference 说,

动态类型允许其发生的操作绕过编译时类型检查。相反,这些操作是在运行时解决的。

所以你可以定义一个方法:

static int GetLength<T>(T obj)
{
    return Marshal.SizeOf<T>();
}

然后通过反射将T类型的实例创建为动态:

dynamic obj = Activator.CreateInstance(field.FieldType.GetTypeInfo());
int length = GetLength(obj);

运行时会为方法选择一个合适的类型参数T。

此解决方案有一个限制,即您无法创建没有默认构造函数的类型的实例。您可以定义一个没有实际字段的包装类Wrapper&lt;T&gt;,并将其创建为运行时以确保构造函数正常工作。但我不知道它是否有效。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-07-07
    • 1970-01-01
    • 1970-01-01
    • 2014-07-21
    • 2011-05-07
    • 2018-08-12
    相关资源
    最近更新 更多