Thursday, August 09, 2007

Visual Studio data visualizers or Writing your own debug data viewer

You may have noticed that in debug mode, in Visual Studio, you have a little magnifier glass next to some of the variables in Autos, Local or Watch debug windows. Once you click on it, you get to visualize your data in a more comprehensive way. A good example are the DataSet Visualizer or the DataTable Visualizer which show you in a normal DataGridView a DataSet or DataTable.

The good news is that you can build your own visualizers and that in a very simple way. Here are the quick steps to achieving this, followed by some links to other people detailing:

  1. Create a new Visual Studio class library project
  2. Add a reference to the Microsoft.VisualStudio.DebuggerVisualizers library you can find directly in the .NET tab
  3. Go to Add New Item and choose Debugger Visualizer. That will create a small class for you with ToDos and stuff like that. What is important is that you don't really need to declare the Type of your data object in the class, as suggested by the template.
  4. Remove everything from the class except the override of the Show method
  5. Change the Show method in order to use your own data type.
  6. Add a reference to System.Windows.Forms
  7. Add a Windows Form to your library and make it display your data the way you like it
  8. Add the following lines to decorate the namespace of your visualizer class:

[assembly : DebuggerVisualizer(typeof (--YourVisualizer--),
Target = typeof (--Your Type--),
Description = "--Your Type-- Visualizer")]
namespace ...

Warning: use a different description from whatever default or own visualizers that are already there. Use stuff like "Siderite's DataTable Visualizer" not "DataTable Visualizer", since there is already an out-of-the-box visualizer with the same name and you won't get to see yours.

Now compile. The resulting DLL can be either copied in My Documents\Visual Studio 2005\Visualizers in this case any contained visualizers will be available only to that user or in C:\Program Files\Microsoft Visual Studio 8\Common7\Packages\Debugger\Visualizers to make the available to all users.

That is it! Now links to others explaining in more detail:
Writing a Visualizer at MSDN
Post on Debugger Visualizers from 4GuysFromRolla
Julia Lerman on Debug Visualizers

A problem with this solution is that the debugger visualizer expects your target type to be ISerializable. But what if it is not? The solution is to add another parameter to the DebuggerVisualizerAttribute like this:
[assembly : DebuggerVisualizer(typeof (--YourVisualizer--),
typeof (--YourVisualizerObjectSource--),
Target = typeof (--Your Type--),
Description = "--Your Type-- Visualizer")]
namespace ...

You see, the debugging is done through communication between a debuggee and a debugger. The VisualizerObjectSource is the debugee and the default one tries to serialize the target object and send it to the debugger. What you have to do it create your own class, inheriting from VisualizerObjectSource and overriding public void GetData(object target, System.IO.Stream outgoingData). This method has access to the actual object, so you can transform it into any other object, one that can be serializable.

A simple example is a DataView or a DataRow. You take the DataRow, you add it to a Table and you return the DataTable, which is serializable.

Another issue you might stumble upon is a weird Access Denied error for the DLL containing the visualizers, especially after adding a VisualizerObjectSource to the library. The solution is to add trust level to full to the site you are debugging. I am looking for a more elegant solution, but so far what you have to do is add this to the web.config of the site you are debugging:

<trust level="Full" originUrl="" />

More links, specific to this update:
RemoteObjectSourceException: Graphics is not marked as serializable
Visualizers For Web Debugging