给定一个FieldInfo对象和一个对象,我需要得到该字段的实际字节表示。我知道该字段是 int,Int32,uint,short 等。

如何获得实际的字节表示? BinaryFormatter.Serialize无济于事,因为它会给我提供比我需要的更多信息(它还记录类型名称等)。 Marshal 类似乎没有使用字节数组的设施(但也许我错过了一些东西)。

由于

有帮助吗?

解决方案

如果您真正想要的是将结构作为字节数组传输,您也可以尝试以下代码:

int rawsize = Marshal.SizeOf(value);
byte[] rawdata = new byte[rawsize];
GCHandle handle = GCHandle.Alloc(rawdata, GCHandleType.Pinned);
Marshal.StructureToPtr(value, handle.AddrOfPinnedObject(), false);
handle.Free();

这会将给定对象 value 转换为字节数组rawdata。我从我之前编写的代码中获取了这些内容,您可能需要根据自己的需要调整它以使其真正起作用。我使用它与一些具有用户定义结构的硬件进行通信,但它也适用于内置类型(毕竟,它们是结构,不是吗?)

要使结构成员正确对齐,请使用StructLayout属性指定一个字节对齐:

[StructLayout(LayoutKind.Sequential, Pack = 1)]

然后根据字段的需要使用MarshalAs属性,例如对于内联数组:

[MarshalAs(UnmanagedType.ByValArray, SizeConst = 8)]
byte[] _state;

从字节数组中获取结构的代码是这样的:

public T GetValue<T>()
{
    GCHandle handle = GCHandle.Alloc(RawValue, GCHandleType.Pinned);
    T structure = (T)Marshal.PtrToStructure(handle.AddrOfPinnedObject(), 
                      typeof(T));
    handle.Free();
    return structure;
}

当然,你需要知道你想要的类型。

请注意,这不会为自身处理字节序。在我的项目中,大多数字段只有一个字节,所以没关系,但对于它所做的几个字段,我只是将字段设为私有,并添加了可以处理字节序的公共属性( Jon Skeet从评论到他的回答的链接可能对你有帮助,我为此写了一些实用功能,因为我只需要少)。

当我需要这个时,我创建了一个Message类来存储原始值(因此GetValue方法,顶部的代码实际上是SetValue方法的主体)并且有一些很好的方便方法来获取格式化的值等

其他提示

使用BitConverter.GetBytes()

首先必须将值转换为它的本机类型,而不是使用BitConverter来获取字节:

byte[] Bytes;

if (valType == typeof(int))
{
    int intVal = (int) GetFieldValue(....);
    Bytes = BitConverter.GetBytes(intVval);
} 
else if (valType == typeof(long))
{
    int lngVal = (long) GetFieldValue(....);
    Bytes = BitConverter.GetBytes(lngVal);
} else ....

你的意思是明确的内存表示吗? BitConverter.GetBytes(通过反射适当选择一个重载)将返回一个字节表示,但不一定是它当前在内存中的内容。

也许如果您提供有关您为什么要这样做的更多信息,我们将能够更好地为您提供帮助。

编辑:我应该在我能想到的任何明智的情况下添加它,BitConverter 给你与内存中相同的表示 - 但可能有奇怪的情况涉及字节序和可能奇怪的架构与不同浮点表示可能会产生奇怪的结果。

编辑:这是一个完整的示例程序,演示了如何实现它:

using System;
using System.Reflection;

public class Test
{
    public int x = 300;

    static void Main()
    {
        Test instance = new Test();
        FieldInfo field = typeof(Test).GetField("x");

        MethodInfo converter = typeof(BitConverter).GetMethod("GetBytes", 
            new Type[] {field.FieldType});

        if (converter == null)
        {
            Console.WriteLine("No BitConverter.GetBytes method found for type "
                + field.FieldType);            
        }
        else
        {
            byte[] bytes = (byte[]) converter.Invoke(null,
                new object[] {field.GetValue(instance) });
            Console.WriteLine("Byte array: {0}", BitConverter.ToString(bytes));
        }        
    }
}
许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top