2014-12-01 50 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