43.3. Visualizers

The last part of this chapter looks at a concept in Visual Studio 2008 that can be used to help debug more complex data structures. Two of the most common data types programmers work with are Strings and DataTables. Strings are often much larger than the area that can be displayed within a tooltip, and the structure of the DataTable object is not suitable for displaying in a tooltip, even using a type proxy. In both of these cases, a visualizer has been created that enables the data to be viewed in a sensible format.

Once a visualizer has been created for a particular type, a magnifying glass icon appears in the first line of the debugger tooltip. Clicking this icon displays the visualizer. Figure 43-7 shows the Text Visualizer dialog that appears.

Figure 43.7. Figure 43-7

Before you can start writing a visualizer, you need to add a reference to the Microsoft.VisualStudio.DebuggerVisualizers namespace. To do this, right-click the project in the Solution Explorer and select Add Reference from the context menu. You should also add this namespace as an import to any classes for which you plan to create debugger visualizers.

A visualizer is typically made up of two parts: the class that acts as a host for the visualizer and is referenced by the DebuggerVisualizer attribute applied to the class being visualized, and the form that is then used to display, or visualize, the class. Figure 43-8 shows a simple form, CustomerForm, which can be used to represent the customer information. This is just an ordinary Windows Form with a couple of TextBox controls, a DataGridView control, and a Button. The only unique aspect to this form is that it has been marked as Serializable, and its constructor has been changed to accept a Customer object, from which the customer information is extracted and displayed, as shown in the following listing:

[Serializable()]
public partial class CustomerForm : Form
{
    public CustomerForm(Customer c)
    {
        InitializeComponent();

        this.txtCustomerId.Text = c.CustomerId.ToString();
        this.txtCustomerName.Text = c.CustomerName;
        this.dgOrders.DataSource = c.Orders;
    }

    private void btnOk_Click(object sender, EventArgs e)
    {
        this.DialogResult = DialogResult.OK;
        this.Close();
    }
}

Figure 43.8. Figure 43-8

The next stage is to wire this form up to be used as the visualizer for the Customer class. This is done by creating the nested CustomerVisualizer class, which inherits from the DialogDebuggerVisualizer abstract class, as shown in the following code:

[Serializable()]
[DebuggerDisplay("Customer {CustomerName} has {Orders.Count} orders")]
[DebuggerTypeProxy(GetType(Customer.CustomerProxy))]
[DebuggerVisualizer(GetType(Customer.CustomerVisualizer))]
public class Customer
{
    ...

    public class CustomerVisualizer : DialogDebuggerVisualizer
    {
        protected override void Show(
                            IDialogVisualizerService windowService,
                            IVisualizerObjectProvider objectProvider)
        {
            Customer c = (Customer)objectProvider.GetObject();
            CustomerForm cf = new CustomerForm(c);
            windowService.ShowDialog(cf);
        }
    }
}

Unlike the type proxy, which interacts with the actual Customer object being debugged, visualizers need to be able to serialize the class being debugged so the class can be moved from the process being debugged to the process that is doing the debugging (and will subsequently be shown the visualizer). As such, both the Customer and Order classes need to be marked with the Serializable attribute.

The Show method of the CustomerVisualizer class does three things. To display the Customer object being debugged, first you need to get a reference to this object. You do this via the GetObject method on the ObjectProvider object. Because the communication between the two processes is done via a stream, this method does the heavy lifting associated with deserializing the object so you can work with it.

Next you need to pass the Customer object to a new instance of the CustomerForm. Finally, use the ShowDialog method on the WindowService object to display the form. It is important that you display the form using this object because it will ensure that the form is displayed on the appropriate UI thread.

Lastly, note that the CustomerVisualizer class is referenced in the DebuggerVisualizer attribute, ensuring that the debugger uses this class to load the visualizer for Customer objects.

As a side note, if you write components and want to ship visualizers separately from the components themselves, visualizers can be installed by placing the appropriate assembly into either the C:Program FilesMicrosoft Visual Studio 9.0Common7PackagesDebuggerVisualizers directory, or the DocumentsVisual Studio 2008Visualizers directory.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.138.37.20