2014-12-01 53 views
1

其中一个简单的技巧我喜欢在C#中使用的被重写ToString()使得调试器显示在监视窗口开发人员指定的,人类可读的字符串。这真的很方便。转换字节数组中VS2013调试器STRUCT

目前,我在调试是MODBUS/TCP的轻微变体的256字节的数据包。我不希望在监视窗口中查看256个数组索引,而是希望看到像“transaction_id_high”,“transaction_id_low”等等,其中映射为1:1,因为这些字段是在结构中定义的。

当我试图把(ModBusPacket)response_buffer在监视窗口,看看会发生什么,它答道Cannot convert type 'byte[]' to 'ModBusPacket'

有没有人曾经试图做到这一点,成功了吗?

ModBusPacket:

public struct ModBusPacket 
{ 
    char transaction_id_high; 
    char transaction_id_low; 
    char protocol_id_high; 
    char protocol_id_low; 
    char unit_id; 
    char function_code; 
    char sub_unit_id; 
    char[] data; 
} 

的字节数组只是

byte[] response_buffer = new byte[256]; 
+0

看看'元帅'级。 – SLaks 2014-12-01 16:02:53

+1

如果您显示“Struct”的结构以及与您的问题和/或问题有关的所有相关代码,它确实有帮助。我们不能看到你所看到 – MethodMan 2014-12-01 16:03:01

+0

如果你的'ModBusPacket'有构造函数/帮手从数组创建 - 您可以使用即时窗口来构造对象('新ModBusPacket(response_buffer)'),看看它的属性。 – 2014-12-01 16:03:02

回答

1

如果你的包是基于this,我不会建议使用char表示字节,因为在C char#是16位数值(有序)值。相反,我建议对于8位无符号值使用byte,对于16位无符号值,推荐使用UInt16。然后,你可以这样做:

[StructLayout(LayoutKind.Sequential)] 
public struct ModBusPacket 
{ 
    // http://en.wikipedia.org/wiki/Modbus#Frame_format 
    // The byte order is Big-Endian (first byte contains MSB). 
    public const bool IsLittleEndian = false; 

    public UInt16 TransactionIdentifier; 
    public UInt16 ProtocolIdentifier; 
    public UInt16 Length; 
    public byte UnitIdentifier; 
    public byte FunctionCode; 
    public byte[] Data; 

    static int PostIncrement(ref int index, int inc) 
    { 
     int old = index; 
     index += inc; 
     return old; 
    } 

    static byte[] ElementArray(byte[] buffer, ref byte[] swapBuffer, ref int index, int size) 
    { 
     if (swapBuffer == null || swapBuffer.Length < size) 
      Array.Resize(ref swapBuffer, size); 
     Array.Copy(buffer, PostIncrement(ref index, size), swapBuffer, 0, size); 
     if (BitConverter.IsLittleEndian != IsLittleEndian) 
      Array.Reverse(swapBuffer); 
     return swapBuffer; 
    } 

    public ModBusPacket(byte[] buffer) 
    { 
     int pos = 0; 
     byte[] swapBuffer = null; 

     TransactionIdentifier = (buffer.Length >= pos + 2 ? BitConverter.ToUInt16(ElementArray(buffer, ref swapBuffer, ref pos, 2), 0) : (UInt16)0); 
     ProtocolIdentifier = (buffer.Length >= pos + 2 ? BitConverter.ToUInt16(ElementArray(buffer, ref swapBuffer, ref pos, 2), 0) : (UInt16)0); 
     Length = (buffer.Length >= pos + 2 ? BitConverter.ToUInt16(ElementArray(buffer, ref swapBuffer, ref pos, 2), 0) : (UInt16)0); 
     UnitIdentifier = (buffer.Length >= pos + 1 ? buffer[PostIncrement(ref pos, 1)] : (byte)0); 
     FunctionCode = (buffer.Length >= pos + 1 ? buffer[PostIncrement(ref pos, 1)] : (byte)0); 
     var length = Math.Max(buffer.Length - pos, 0); 
     Data = new byte[length]; 
     if (length > 0) 
      Array.Copy(buffer, pos, Data, 0, length); 
    } 

    public override string ToString() 
    { 
     return ObjectExtensions.ToStringWithReflection(this); 
    } 
} 

public static class ObjectExtensions 
{ 
    public static string ToStringWithReflection<T>(this T obj) 
    { 
     if (obj == null) 
      return string.Empty; 
     var type = obj.GetType(); 
     var fields = type.GetFields(); 
     var properties = type.GetProperties().Where(p => p.GetIndexParameters().Length == 0 && p.GetGetMethod(true) != null); 

     var values = new List<KeyValuePair<string, object>>(); 
     Array.ForEach(fields, (field) => values.Add(new KeyValuePair<string, object>(field.Name, field.GetValue(obj)))); 
     foreach (var property in properties) 
      if (property.CanRead) 
       values.Add(new KeyValuePair<string, object>(property.Name, property.GetValue(obj, null))); 

     return values.Aggregate(new StringBuilder(), (s, pair) => (s.Length == 0 ? s.Append("{").Append(obj.GetType().Name).Append(": ") : s.Append("; ")).Append(pair)).Append("}").ToString(); 
    } 
} 

已经这样做了,在即时窗口中,您可以在即时窗口中键入buffer.ToPacket()或监视窗口,看到格式化的数据。或者你可以使用conversion operator来将你的字节数组转换为ModBusPacket,如果这会更有吸引力。

+0

非常感谢dbc!你提出的建议教会了我很多。它几乎可以工作,我应该能够找出扭曲,这正是BitConverter没有正确转换长度。除此之外,这个答案是完美的。再次感谢! – Dave 2014-12-23 15:01:41

+1

呵呵...... BitConverter的排列顺序与我的数据相反。所有其他的可能工作,因为他们的价值为0. :) – Dave 2014-12-23 15:07:47

+0

@Dave - 我更新了你的排序反馈的答案。 – dbc 2014-12-23 22:42:02