Criar visualizadores de dados personalizados

Um visualizador faz parte da interface do usuário do depurador que exibe uma variável ou objeto de uma maneira Visual Studio apropriada para seu tipo de dados. Por exemplo, um visualizador HTML interpreta uma cadeia de caracteres HTML e exibe o resultado como ele seria exibido em uma janela do navegador. Um visualizador de bitmap interpreta uma estrutura de bitmap e exibe o gráfico que ele representa. Alguns visualizadores permitem modificar, bem como exibir os dados.

O depurador do Visual Studio inclui seis visualizadores padrão. Os visualizadores de texto, HTML, XML e JSON funcionam em objetos de cadeia de caracteres. O visualizador de árvore do WPF exibe as propriedades de uma árvore visual de objeto WPF. O visualizador de conjuntos de dados funciona para objetos DataSet, DataView e DataTable.

Mais visualizadores podem estar disponíveis para download da Microsoft, de terceiros e da comunidade. Você também pode escrever seus próprios visualizadores e instalá-los no Visual Studio depurador.

No depurador, um visualizador é representado por um ícone de lupa VisualizerIcon. Você pode selecionar o ícone em uma caixa de diálogo DataTip, janela Depurador Watch ou QuickWatch e, em seguida, selecionar o visualizador apropriado para o objeto correspondente.

Gravar visualizadores personalizados

Observação

Para criar um visualizador personalizado para código nativo, consulte o exemplo do Visualizador do Depurador nativo do SQLite. Não há suporte para visualizadores personalizados para aplicativos UWP e Windows 8.x.

Você pode escrever um visualizador personalizado para um objeto de qualquer classe gerenciada com exceção de Object ou Array.

A arquitetura de um visualizador de depurador tem duas partes:

  • O lado do depurador é executado no Visual Studio depurador e cria e exibe a interface do usuário do visualizador.

    Como Visual Studio é executado no runtime .NET Framework, esse componente deve ser gravado para .NET Framework. Por esse motivo, não é possível escrevê-lo para o .NET Core.

  • O lado a ser depurado é executado dentro do processo que o Visual Studio está depurando (o lado a ser depurado). O objeto de dados a ser visualizado (por exemplo, um objeto String) existe no processo de depuração. O lado de depuração envia o objeto para o lado do depurador, que o exibe na interface do usuário que você cria.

    O runtime para o qual você cria esse componente deve corresponder ao em que o processo de depuração será executado, ou seja, .NET Framework ou .NET Core.

O lado do depurador recebe o objeto de dados de um provedor de objetos que implementa a IVisualizerObjectProvider interface . O lado de depuração envia o objeto por meio da origem do objeto, que é derivada de VisualizerObjectSource .

O provedor de objetos também pode enviar dados de volta para a origem do objeto, o que permite que você escreva um visualizador que possa editar dados. Você substitui o provedor de objetos para se falar com o avaliador de expressão e a origem do objeto.

O lado do depurador e o lado do depurador se comunicam entre si por meio de métodos que serializam um objeto de dados em um e Stream desseerializam o de volta em um objeto Stream Stream de dados.

Você pode escrever um visualizador para um tipo genérico somente se o tipo for um tipo aberto. Essa restrição é a mesma que a restrição ao usar o atributo DebuggerTypeProxy. Para obter detalhes, consulte Usar o atributo DebuggerTypeProxy.

Os visualizadores personalizados podem ter considerações de segurança. Consulte Considerações de segurança do visualizador.

As etapas a seguir dão uma visão geral de alto nível da criação do visualizador. Para obter instruções detalhadas, consulte instruções passo a passo: escrever um visualizador em C# ou passo a passo: escrever um visualizador em Visual Basic.

Para criar o lado do depurador

Para criar a interface do usuário do visualizador no lado do depurador, você cria uma classe que herda de e substitui o método para exibir a DialogDebuggerVisualizer Microsoft.VisualStudio.DebuggerVisualizers.DialogDebuggerVisualizer.Show interface. Você pode usar IDialogVisualizerService para exibir Windows, diálogos e controles em seu visualizador.

  1. Use os métodos IVisualizerObjectProvider para obter o objeto visualizado no lado do depurador.

  2. Crie uma classe que herda de DialogDebuggerVisualizer.

  3. Substitua o método Microsoft.VisualStudio.DebuggerVisualizers.DialogDebuggerVisualizer.Show para exibir sua interface. Use IDialogVisualizerService métodos para exibir Windows, caixas de diálogo e controles em sua interface.

  4. Aplique DebuggerVisualizerAttribute , dando a ele o visualizador para exibir ( DialogDebuggerVisualizer ).

Considerações especiais do lado do depurador para .NET 5.0+

Os Visualizadores Personalizados transferem dados entre os lados do depurador e do depurador por meio da serialização binária usando a classe BinaryFormatter por padrão. No entanto, esse tipo de serialização está sendo reduzido no .NET 5 e superior devido a preocupações de segurança em relação a suas vulnerabilidades infixáveis. Além disso, ele foi marcado como completamente obsoleto no ASP.NET Core 5 e seu uso será a lançar, conforme descrito na documentação ASP.NET Core . Esta seção descreve as etapas que você deve seguir para garantir que o visualizador ainda tenha suporte neste cenário.

  • Por motivos de compatibilidade, o método que Show foi substituído na seção anterior ainda recebe um IVisualizerObjectProvider . No entanto, a partir do Visual Studio 2019 versão 16.10, ele é, na verdade, do tipo IVisualizerObjectProvider2 . Por esse motivo, caste o objectProvider objeto para a interface atualizada.

  • Ao enviar objetos, como comandos ou dados, para o lado de depuração, use o método para passá-lo para um fluxo, ele determinará o melhor formato de serialização a ser usado com base no runtime do processo IVisualizerObjectProvider2.Serialize de depuração. Em seguida, passe o fluxo para o IVisualizerObjectProvider2.TransferData método .

  • Se o componente do visualizador do lado de depuração precisar retornar algo para o lado do depurador, ele estará localizado no objeto retornado pelo método Stream TransferData . Use o IVisualizerObjectProvider2.GetDeserializableObjectFrom método para obter uma instância dele e IDeserializableObject processá-la conforme necessário.

Consulte a seção Considerações especiais do lado de depuração para .NET 5.0+ para saber quais outras alterações são necessárias no lado do rodo de depuração ao usar a Serialização Binária não tem suporte.

Observação

Se você quiser obter mais informações sobre o problema, consulte o guia de segurança BinaryFormatter.

Para criar a origem do objeto visualizador para o lado do rodo de depuração

No código lateral do depurador, edite o , dando a ele o tipo a ser visualizado (a origem do objeto do lado do rodo de DebuggerVisualizerAttribute depuração) ( VisualizerObjectSource ). A Target propriedade define a origem do objeto. Se você omitir a origem do objeto, o visualizador usará uma origem de objeto padrão.

O código lateral de depuração contém a origem do objeto que é visualizada. O objeto de dados pode substituir métodos de VisualizerObjectSource . Uma DLL do lado de depuração é necessária se você quiser criar um visualizador autônomo.

No código do lado do rodo de depuração:

  • Para permitir que o visualizador edite objetos de dados, a origem do objeto deve herdar de VisualizerObjectSource e substituir os métodos ou TransferData CreateReplacementObject .

  • Se você precisar dar suporte a vários destinos em seu visualizador, poderá usar os seguintes TFMs (Monikers de Estrutura de Destino) no arquivo de projeto do lado do rodo de depuração.

    <TargetFrameworks>net20;netstandard2.0;netcoreapp2.0</TargetFrameworks>
    

    Esses são os únicos TFMs com suporte.

Considerações especiais do lado de depuração para o .NET 5.0+

Importante

Etapas adicionais podem ser necessárias para que um visualizador funcione a partir do .NET 5.0 devido a preocupações de segurança relacionadas ao método de serialização binária subjacente usado por padrão. Leia esta seção antes de continuar.

  • Se o visualizador implementar o método , use o método recém-adicionado TransferData que está disponível na versão mais recente do GetDeserializableObject VisualizerObjectSource . O que ele retorna ajuda a determinar o formato de serialização do objeto (binário ou JSON) e desseerializar o objeto subjacente para que ele possa IDeserializableObject ser usado.

  • Se o lado do depurador retorna dados para o lado do depurador como parte da chamada, serialize a resposta ao fluxo do lado do depurador por meio TransferData do método Serialize .

Confira também