给定一个 FieldInfo 对象和一个对象,我需要获取该字段的实际字节表示。我知道该领域是要么int,Int32,uint,short
等。
如何获得实际的字节表示?BinaryFormatter.Serialize 无济于事,因为它会给我提供比我需要的更多的信息(它还记录类型名称等)。该类Marshal
似乎没有使用字节数组的设施(但也许我遗漏了一些东西)。
谢谢
给定一个 FieldInfo 对象和一个对象,我需要获取该字段的实际字节表示。我知道该领域是要么int,Int32,uint,short
等。
如何获得实际的字节表示?BinaryFormatter.Serialize 无济于事,因为它会给我提供比我需要的更多的信息(它还记录类型名称等)。该类Marshal
似乎没有使用字节数组的设施(但也许我遗漏了一些东西)。
谢谢
使用 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 ....
如果您真正想要的是将结构作为字节数组传输,您也可以尝试以下代码:
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();
这会将给定的对象值转换为字节数组 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 (with an overload suitably chosen by reflection) will return you a byte representation, but not necessarily what it is currently in memory.
也许如果您提供更多关于您为什么想要这个的信息,我们将能够更好地为您提供帮助。
编辑:我应该补充一点,在我能想到的任何合理情况下,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));
}
}
}