C# 使用C获取Int/short/byte结构字节表示#
给定一个FieldInfo对象和一个object,我需要得到字段的实际字节表示形式。我知道该字段是C# 使用C获取Int/short/byte结构字节表示#,c#,reflection,marshalling,binary-data,C#,Reflection,Marshalling,Binary Data,给定一个FieldInfo对象和一个object,我需要得到字段的实际字节表示形式。我知道该字段是int、Int32、uint、short等 如何获得实际的字节表示?Serialize不会有帮助,因为它会给我比我需要的更多的信息(它还记录类型名等)。Marshal类似乎没有使用字节数组的工具(但可能我遗漏了一些东西) 感谢使用BitConverter.GetBytes() 首先必须将值转换为其本机类型,然后使用位转换器获取字节: byte[] Bytes; if (valType == typ
int、Int32、uint、short等
如何获得实际的字节表示?Serialize不会有帮助,因为它会给我比我需要的更多的信息(它还记录类型名等)。Marshal
类似乎没有使用字节数组的工具(但可能我遗漏了一些东西)
感谢使用BitConverter.GetBytes()
首先必须将值转换为其本机类型,然后使用位转换器获取字节:
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都会给您提供与内存中相同的表示形式——但是可能会有一些奇怪的情况,包括endianness和可能具有不同浮点表示形式的奇怪架构,这可能会产生奇怪的结果
编辑:下面是一个完整的示例程序,演示了如何进行:
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));
}
}
}
如果您真正想要的是将结构作为字节数组传输,您也可以尝试以下代码:
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;
}
public T GetValue()
{
GCHandle handle=GCHandle.Alloc(原始值,GCHandleType.pinted);
T structure=(T)Marshal.PtrToStructure(handle.addrofPindedObject(),
(T)型;
handle.Free();
回报结构;
}
当然,您需要知道要使其工作的类型
请注意,这不会自行处理endianness。在我的项目中,大多数字段只有一个字节,所以这无关紧要,但对于有字节的少数字段,我只是将字段设置为私有字段,并添加了公共属性,以处理endianness(从一条评论到他的答案可能会帮到你,我为此编写了一些实用函数,因为我只需要几个)
当我需要它时,我创建了一个消息类来存储原始值(因此是GetValue方法,顶部的代码实际上是SetValue方法的主体),并使用了一些非常方便的方法来格式化值等。我也准备发布它,但GetBytes似乎没有接受对象的重载,也就是说,仍然需要先编写转换为适当类型的代码。或者我遗漏了什么?不,你没有遗漏任何东西-你必须找出调用的方法。不过很容易做到——我将使用代码示例进行编辑。我正在尝试将我的对象序列化为硬件所需的特定格式。我有一个消息对象,我用该对象拥有的特殊方法序列化它。它看起来像:class msg:mbase{uint x;}
mbase移动msg的所有字段并序列化它们。当然,理想情况下,我想要控制endianness,即getBigEndianBytes()。如果您想要控制endianness,请使用Nah中的EndianBitConverter,使用反射:)谢谢,这更像我想要的。您如何确保结构按照您希望的方式对齐?