Debugger Visualizers and arrays

All of a sudden I was hit by multiple sources on Debugger Visualizers. A Debugger Visualizer is a way to create a different view on a .NET type during debugging. It will show itself as a magnifying glass when you watch a variable or expression.



If you select the magnifying glass, it will show a popup menu with the registered visualizers. You pick one and it will show the variable or expression in an easier way. Example screenshots below. And if you don’t know visualizers yet, you MUST check out the DataSet Visualizer, which comes with VS2005.


Here are some of the resources that I read and used:



I wanted a byte array visualizer for myself! In my programming on a protocol library for game servers (nearly ready for first release) I need to take a look at byte[] all the time. Not very handy I can tell you. As the one in the MSDN article was for FileInfo and MemoryStream,  I ventured off to create one myself.


These are the ingredients for a Debugger Visualizer:



  1. A Visualizer class (in my case ByteArrayVisualizer, just like in the MSDN article) derived from base class DialogDebuggerVisualizer. It needs to override the Show method.
    This methods offers two input parameters: IDialogVisualizerService and IVisualizerObjectProvider.
    The first one can be used to show your custom form with a call to IDialogVisualizerService.Show. This is not obligatory, though.
    The second parameter hands you the data to visualize through a deserialization mechanism. You will typically call IVisualizerObjectProvider.GetObject to get at it. All you need to do is construct a dialog or form to visualize the data you got and show the form.
  2. For custom types like Customer where you need a visualizer you will add the DebuggerVisualizerAttribute to your type. In cases where you do do not have access to the types or sources, you will need a assembly level attribute like so
    [assembly: System.Diagnostics.DebuggerVisualizer(
      typeof(ByteArrayVisualizer),
      typeof(VisualizerObjectSource), Target = typeof(Byte[]),
      Description = ByteArrayVisualizer.Description)]

    The parameters and attributes of this attribute represent (in order)

    • the kind of Visualizer to register
    • the type of object source to use (more on that in a minute),
    • the target aka the type you are registering for and
    • a description which will show up on the context menu in VS2005

The simplest possible visualizer would look like this then:


using System;
using
System.IO;
using
System.Windows.Forms;
using
System.ComponentModel.Design;
using
System.Text;
using Microsoft.VisualStudio.DebuggerVisualizers;


[assembly: System.Diagnostics.DebuggerVisualizer(
  typeof(ByteArrayVisualizer
),
  typeof(VisualizerObjectSource), Target = typeof(byte[]
),
  Description = ByteArrayVisualizer
.Description)]
publicclassByteArrayVisualizer
: DialogDebuggerVisualizer
{
  publicconststring Description = “Byte Array Visualizer”
;
  protectedoverridevoid
Show(
      IDialogVisualizerService windowService,
      IVisualizerObjectProvider objectProvider)
  {
    object
data = objectProvider.GetObject();
    MessageBox.Show(Encoding.ASCII.GetString((byte
[])data));
  }
}


And that’s it. Place this code inside of a Class Library project, compile and put the assembly in the folder <My Documents Folder>Visual Studio 2005Visualizers or <VS2005 Install Dir>Common7PackagesDebuggerVisualizers and restart VS2005.


Hold your horses, because the sample above won’t work. This would have worked for any other type, except for the arrays. At least I could not get it to work. Major bummer. The documentation mentions this somewhat indirectly here: “You can write a custom visualizer for an object of any managed class except for Object or Array.


This is very unfortunate. A workaround would be to create a visualizer for a type that uses a byte[] and expose the array as part of the visualizer for the type. Not very flexible if you want ad-hoc viewing of a byte[].


I have also looked into the VisualizerObjectSource mechanism. The idea is that you can use this class to serialize and deserialize the data if it is marked [Serializable] or implements ISerializable. If it doesn’t you would have to create a custom Object Source and (de)serialize the data yourself. This shouldn’t be necessary for a byte[], as it is serializable. Did it anyway, but to no avail.


Sure hope this gets fixed soon. Two weird things (see ‘Array casting weirdness‘) with arrays in one week is just too much.

Advertisements
This entry was posted in Uncategorized. Bookmark the permalink.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google+ photo

You are commenting using your Google+ account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s