为什么此用于构造反序列化单元测试的字节失败?

我有一个简单的结构:

[StructLayout(LayoutKind.Sequential,Pack = 1,CharSet = CharSet.Auto)]
public struct TestStruct
{
    public bool Valid;     // 1
    public UInt64 Value1;  // 8 
    public UInt64 Value2;  // 8
    public float Value3;   // 4
}

以及从字节数组到struct方法的通用方法:

public static T ByteArrayToStructure<T>(byte[] bytes) where T : struct
{
    var handle = GCHandle.Alloc(bytes,GCHandleType.Pinned);
    try 
    {
        return (T) Marshal.PtrToStructure(handle.AddrOfPinnedObject(),typeof(T));
    }
    finally 
    {
        handle.Free();
    }
}

和这个简单的单元测试:

[Test]
public void BytesToMyStruct()
{
    const bool Valid = true;
    const UInt64 Value1 = 1;
    const UInt64 Value2 = 2;
    const UInt64 Value3 = 99;

    var validBytes = BitConverter.GetBytes(Valid);
    var value1Bytes = BitConverter.GetBytes(Value1);
    var value2Bytes = BitConverter.GetBytes(Value2);
    var value3Bytes = BitConverter.GetBytes(Value3);  

    // 1 + 8 + 8 + 4 = 21
    var testBytes = new byte[21];

    Array.Copy(validBytes,testBytes,1);
    Array.Copy(value1Bytes,1,8);
    Array.Copy(value2Bytes,9,8);
    Array.Copy(value3Bytes,17,4);

    var myStruct = ByteUtils.ByteArrayToStructure<TestStruct>(testBytes);

    Assert.That(myStruct.Valid,Is.EqualTo(true));
    Assert.That(myStruct.Value1,Is.EqualTo(1));
    Assert.That(myStruct.Value2,Is.EqualTo(2));
    Assert.That(myStruct.Value3,Is.EqualTo(99));
}

在这个单元测试中,我只是希望手动填充一个字节数组,反序列化为一个结构,并确保该结构的属性等于在字节数组中设置的那些属性。我假设我反复通过Array.Copy手动复制到同一字节数组的方法失败了,原因是在执行单元测试时,我收到一条失败消息,指出未正确设置Value1

Expected: 1
But was:  0

我不确定是否通过手动设置字节数组以进行单元测试来正确设置字节数组。

humingming001 回答:为什么此用于构造反序列化单元测试的字节失败?

根据System.Boolean的Microsoft / Windows API定义,BOOL的默认封送处理行为是4字节整数。因此,Marshal.PtrToStructure假定TestStruct的非托管表示形式为24字节大,而TestStruct.Valid占用了前4个字节,从而抛出了Value1和其他字段。 / p>

您可以通过将[MarshalAs(UnmanagedType.I1)]属性应用于bool字段来更改此行为。

本文链接:https://www.f2er.com/3121204.html

大家都在问