Desenvolvimento - C#

.NET 2.0 - Criando um DebuggerVisualizer

A Microsoft incluiu na versão 2.0 do .NET Framework uma possibilidade de criar um debugger customizado para um determinado objeto que temos.

por Israel Aéce



function doClick(index, numTabs, id) { document.all("tab" + id, index).className = "tab"; for (var i=1; i A Microsoft incluiu na versão 2.0 do .NET Framework uma possibilidade de criar um debugger customizado para um determinado objeto que temos. Isso permite-nos criar uma interface mais amigável em relação à qual é fornecida quando utilizamos o debug do Visual Studio .NET 2005. Essa técnica é chamada de Debugger Visualizer. Você pode escrever esse visualizador para qualquer objeto da sua aplicação, com excessão de um Object ou Array.

A arquitetura do debugger está dividida em duas partes:

  • O debugger side corre dentro do debugger do Visual Studio .NET, podendo ser criado e exibido uma interface para seu visualizador.
  • O debuggee side corre dentro do processo que o Visual Studio .NET está depurando.

O objeto que você está querendo visualizar (uma String ou Image, por exemplo) existe dentro do processo debuggee. Logo, o debuggee side deve mandar os dados para o debugger side que, por sua vez, exibe o objeto para que o desenvolvedor possa depurar. Essa visualização é criada por nós que, ainda nesse artigo, veremos como criá-la.

O debugger side recebe o objeto que será visualizado através de um object provider, o qual implementa uma interface chamada IVisualizerObjectProvider. O debuggee side envia o objeto através de um object source, o qual deriva de uma classe chamada VisualizerObjectSource. O object provider também devolve o objeto para o object source, permitindo assim, além de exibir o objeto, editá-lo no visualizador (se assim desejar) e devolvê-lo para a aplicação. Essa comunicação é efetuada através de um objeto Stream.

Para criarmos este visualizador, primeiramente precisamos marcar a classe como sendo uma classe de DebuggerVisualizer e, para isso, é fornecido um atributo chamado DebuggerVisualizer (usado a nível de assembly ou classe) para definí-la como um visualizador. Além disso, a classe deverá obrigatoriamente herdar de uma classe abstrata chamada DialogDebuggerVisualizer e implementar o método chamado Show para customizar a visualização.

O atributo DebuggerVisualizer, contido dentro do Namespace System.Diagnostics, fornece mais alguns parâmetros para a configuração do visualizador. O primeiro parâmetro é tipo, ou seja, a classe derivada DialogDebuggerVisualizer que é o nosso visualizador efetivamente; já o segundo especifica o tipo de objeto que fará a comunicação entre o debugger side e o debuggee side e, se não informado, um default será utilizado. O restante, chamado de "Named Parameters", você deve especificar o tipo de objeto que o visualizador irá trabalhar (uma String ou Image, por exemplo) e no outro, é o nome que aparecerá dentro do Visual Studio .NET 2005, para permitir visualização. Para ilustrar, veremos abaixo o código que cria o visualizador:

using System;
using Microsoft.VisualStudio.DebuggerVisualizers;
using System.Windows.Forms;
using System.Drawing;
using System.Diagnostics;

[
    assembly: DebuggerVisualizer(typeof(DebugTools.ImageVisualizer),
    typeof(VisualizerObjectSource),
    Target = typeof(System.Drawing.Image),
    Description = "Image Visualizer")
]
namespace DebugTools
{
    public class ImageVisualizer : DialogDebuggerVisualizer
    {
        protected override void Show(IDialogVisualizerService windowService, 
            IVisualizerObjectProvider objectProvider)
        {
            Image data = (Image)objectProvider.GetObject();

            using(ImageVisualizerForm f = new ImageVisualizerForm())
            {
                f.Image = data;
                windowService.ShowDialog(f);
            }
        }
    }
}
Imports System
Imports Microsoft.VisualStudio.DebuggerVisualizers
Imports System.Windows.Forms
Imports System.Drawing
Imports System.Diagnostics

<_
    Assembly: DebuggerVisualizer(GetType(DebugTools.ImageVisualizer), _
    GetType(VisualizerObjectSource), _
    Target := GetType(System.Drawing.Image), _
    Description := "Image Visualizer") _
>
Namespace DebugTools
    Public Class ImageVisualizer
        Inherits DialogDebuggerVisualizer

        Protected Overrides Sub Show(IDialogVisualizerService windowService, _
            IVisualizerObjectProvider objectProvider)

            Image data = DirectCast(objectProvider.GetObject(), Image)

            Using(ImageVisualizerForm f = New ImageVisualizerForm())
                f.Image = data
                windowService.ShowDialog(f)
	    End Using
        End Sub

    End Class
End Namespace
C# VB.NET

Note que foi criado um formulário chamado ImageVisualizerForm. Este formulário é encarregado de receber a imagem e exibí-la. Não há segredos nele, ou seja, apenas foi criada uma propriedade chamada Image que recebe a imagem vinda do object provider. O primeiro parâmetro do método Show, chamado windowService do tipo IDialogVisualizerService, fornece métodos para que o visualizador possa estar exibindo formulários, controles e janelas de diálogo.

Se você quiser que o seu visualizador edite o objeto e o devolva para a aplicação, terá que sobrescrever os métodos TransferData ou CreateReplacementObject da classe VisualizerObjectSource.

Deploy

Para que possamos utilizar o visualizador dentro do Visual Studio .NET 2005 teremos que compilar o projeto e, com a DLL gerada, colocá-la dentro do diretório <Diretorio VS.NET>\Common7\Packages\Debugger\Visualizers. Quando abrir o Visual Studio, já terá acesso ao visualizador, assim como é mostrado através da imagem abaixo:

Figura 1 - DebuggerVisualizer em funcionamento.
Israel Aéce

Israel Aéce - Especialista em tecnologias de desenvolvimento Microsoft, atua como desenvolvedor de aplicações para o mercado financeiro utilizando a plataforma .NET. Como instrutor Microsoft, leciona sobre o desenvolvimento de aplicações .NET. É palestrante em diversos eventos Microsoft no Brasil e autor de diversos artigos que podem ser lidos a partir de seu site http://www.israelaece.com/. Possui as seguintes credenciais: MVP (Connected System Developer), MCP, MCAD, MCTS (Web, Windows, Distributed, ASP.NET 3.5, ADO.NET 3.5, Windows Forms 3.5 e WCF), MCPD (Web, Windows, Enterprise, ASP.NET 3.5 e Windows 3.5) e MCT.