2015-10-26 109 views
2

我想反序列化一个字节数组到一个结构。为什么我的返回对象与我接收的对象不匹配?

这里是我的反序列化功能:

void RawDeserialize(byte[] bytearray, object obj) 
{ 
    int len = Marshal.SizeOf(obj); 

    IntPtr i = Marshal.AllocHGlobal(len); 

    Marshal.Copy(bytearray, 0, i, len); 

    obj = Marshal.PtrToStructure(i, obj.GetType()); 

    Marshal.FreeHGlobal(i); 
} 

我把它与

RawDeserialize(outarr, outbuf); 

哪里outarr是一个长度为22和outbuf中的字节数组是我的结构看起来像这样:

[StructLayout(LayoutKind.Sequential,Size =22)] 
public struct ID_OUTPUT 
{ 
    public HEADER_OUTPUT hdr; //Another struct size=8 
    public byte bType; 
    public byte bRunning; 
    [MarshalAs(UnmanagedType.ByValTStr,SizeConst = 8)] 
    public string softwareName; 
    public short softwareVersion; 
} 

当我在我的反序列化函数中逐步调试时,obj填充了正确的值,但返回outbuf填充零(或从未分配,因为我最初初始化为零)。

我最初的想法是对象没有被引用传递,但我认为这应该工作,因为我发现这个反序列化函数在另一个SO问题上(我没有链接了)。

于是我尝试使用裁判关键字,但后来我得到一个错误无法从裁判ID_OUTPUT转换为参考对象

回答

3

当你在处理多重结构类型和希望的唯一方法这项工作,generics是一个不错的选择。这使您可以使用一个很好的C#语法,而无需将您的实例强制转换为object

// For .Net 4.5 and previous versions 
public static T RawDeserialize<T>(byte[] bytearray) 
    where T : struct 
{ 
    var type = typeof(T); 
    int len = Marshal.SizeOf(type); 

    IntPtr i = IntPtr.Zero; 
    try 
    { 
     i = Marshal.AllocHGlobal(len); 

     Marshal.Copy(bytearray, 0, i, len); 

     return (T)Marshal.PtrToStructure(i, type); 
    } 
    finally 
    { 
     if (i != IntPtr.Zero) 
     { 
      Marshal.FreeHGlobal(i); 
     } 
    } 
} 

用法:

ID_OUTPUT myStruct = RawDeserialize<ID_OUTPUT>(someByteArray); 
ZZZZ myStruct2 = RawDeserialize<ZZZZ>(someByteArray); 

对于.NET 4.5.1+,您可能希望使用sizeof /累得PtrToStructure的仿制版本:

public static T RawDeserialize<T>(byte[] bytearray) 
    where T : struct 
{ 
    int len = Marshal.SizeOf<T>(); 

    IntPtr i = IntPtr.Zero; 
    try 
    { 
     i = Marshal.AllocHGlobal(len); 

     Marshal.Copy(bytearray, 0, i, len); 

     return Marshal.PtrToStructure<T>(i); 
    } 
    finally 
    { 
     if (i != IntPtr.Zero) 
     { 
      Marshal.FreeHGlobal(i); 
     } 
    } 
} 
+0

你为什么这么认为? (我知道你是对的,但一些解释将有助于OP) –

+1

@PatrickHofman OP的对象的使用,而不是实际的类型,加上OP的评论(我想对其他结构使用这种反序列化方法_) – ken2k

+0

好吧,但它是做什么的。为什么它有助于OP? –

3

您正将本地变量obj的引用重新定义为与传递给方法不同的内容。调用方法中的实际引用不会更改。当您将方法签名更改为ref这些变量时,它确实有效,但是您有一个转换问题。

由于您的方法是void,最简单的方法就是返回变量并适当地输入它(或者在需要时将其强制转换)。 (你可以在你的返回变量上使用泛型,无论你最适合什么)。

所需的方法签名:

ID_OUTPUT /* your struct return variable */ RawDeserialize(byte[] bytearray); 

如果问题仅仅是转换问题,此修复它:

ID_OUTPUT obj; 
object outputObject = obj; 
RawDeserialize(bytearray, ref outputObject); 

obj = (ID_OUTPUT)outputObject; 
+0

但我想用这种方法反序列化对于其他结构(ID_OUTPUT除外)。那可能吗? –

+0

查看更新@Seth。 –

+0

是的,更新对我的工作感谢 –

相关问题