Compartilhar via


Adicionar validação de arquitetura personalizada a diagramas de dependência

No Visual Studio, os usuários podem validar o código-fonte em um projeto em relação a um modelo de camada para que possam verificar se o código-fonte está em conformidade com as dependências de um diagrama de dependência. Há um algoritmo de validação padrão, mas você pode definir suas próprias extensões de validação.

Quando o usuário seleciona o comando Validar Arquitetura em um diagrama de dependência, o método de validação padrão é invocado, seguido pelas extensões de validação que foram instaladas.

Observação

Em um diagrama de dependência, a principal finalidade da validação é comparar o diagrama com o código do programa em outras partes da solução.

É possível empacotar essas extensões em uma VSIX (Extensão de Integração do Visual Studio) que pode ser distribuída para outros usuários do Visual Studio. Você pode colocar seu validador em um VSIX por si só ou combiná-lo no mesmo VSIX que outras extensões. Escreva o código do validador em seu próprio projeto do Visual Studio, não no mesmo projeto que outras extensões.

Aviso

Depois de criar um projeto de validação, copie o código de exemplo no final deste tópico e edite-o para suas próprias necessidades.

Requisitos

Confira os Requisitos

Definindo um validador de camada em um novo VSIX

O método mais rápido de criação deum validador é usar o modelo de projeto. Assim, o código e o manifesto VSIX ficam no mesmo projeto.

Para definir uma extensão usando um modelo de projeto

  1. Crie um novo projeto Extensão de Validação do Designer de Camada.

    O modelo cria um projeto que contém um pequeno exemplo.

    Aviso

    Para que o modelo funcione corretamente:

  2. Edite o código para definir sua validação. Para saber mais, consulte Validação de programação.

  3. Para testar a extensão, consulte Validação da camada de depuração.

    Observação

    Seu método será convocado apenas em circunstâncias específicas e os pontos de interrupção não funcionarão automaticamente. Para obter mais informações, consulte Validação da camada de depuração.

  4. Para instalar a extensão na instância principal do Visual Studio ou em outro computador, localize o arquivo .vsix no diretório bin. Copie-o para o computador no qual você deseja instalá-lo e clique duas vezes nele. Para desinstalar, selecione Gerenciar Extensões no menu Extensões.

Adicionar um validador de camada a um VSIX separado

Se você quiser criar um VSIX que contenha comandos, validadores de camada e outras extensões, recomendamos que crie um projeto para definir o VSIX e separar projetos para os manipuladores.

Para adicionar validação de camada a um VSIX separado

  1. Crie um projeto de Biblioteca de Classes. Este projeto contém a classe de validação de camada.

  2. Procure e crie um projeto VSIX em sua solução. Um projeto VSIX contém um arquivo chamado source.extension.vsixmanifest.

  3. Em Gerenciador de Soluções, clique com o botão direito do mouse no menu do projeto VSIX, escolha Definir como Projeto de Inicialização.

  4. Em source.extension.vsixmanifest, em Ativos, adicione o projeto de validação de camada como um componente MEF:

    1. Escolha Novo.

    2. A caixa de diálogo Adicionar Novo Ativo será exibida.

      Tipo = Microsoft.VisualStudio.MefComponent

      Fonte = Um projeto na solução atual

      Projeto = seu projeto de validador

  5. Também adicione o projeto como uma validação de camada:

    1. Escolha Novo.

    2. A caixa de diálogo Adicionar Novo Ativo será exibida.

      Tipo = Microsoft.VisualStudio.ArchitectureTools.Layer.Validator. Essa não é uma das opções na lista suspensa. Você deve inserir o tipo a partir do teclado.

      Fonte = Um projeto na solução atual

      Projeto = seu projeto de validador

  6. Retorne ao projeto de validação de camada e adicione as seguintes referências de projeto:

    Referência O que você pode fazer
    Microsoft.VisualStudio.GraphModel.dll Ler o grafo de arquitetura
    Microsoft.VisualStudio.ArchitectureTools.Extensibility.CodeSchema.dll Ler o DOM de código associado a camadas
    Microsoft.VisualStudio.ArchitectureTools.Extensibility.Layer.dll Ler o modelo de camada
    Microsoft.VisualStudio.ArchitectureTools.Extensibility Ler e atualizar formas e diagramas.
    System.ComponentModel.Composition Definir o componente de validação usando Managed Extensibility Framework (MEF)
    Microsoft.VisualStudio.Modeling.Sdk.[version] Definir extensões de modelo
  7. Copie o código de exemplo no final deste tópico para o arquivo de classe no projeto da biblioteca de validadores para conter o código para sua validação. Para saber mais, consulte Validação de programação.

  8. Para testar a extensão, consulte Validação da camada de depuração.

    Observação

    Seu método será convocado apenas em circunstâncias específicas e os pontos de interrupção não funcionarão automaticamente. Para obter mais informações, consulte Validação da camada de depuração.

  9. Para instalar o VSIX na instância principal do Visual Studio ou em outro computador, localize o arquivo .vsix no diretório bin do projeto VSIX. Copie o arquivo para o computador no qual você deseja instalar o VSIX. Clique duas vezes no arquivo VSIX no Windows Explorer.

Validação de programação

Para definir uma extensão de validação de camada, defina uma classe que tem as seguintes características:

  • A forma geral da declaração é a seguinte:

    using System.ComponentModel.Composition;
    using Microsoft.VisualStudio.ArchitectureTools.Extensibility.CodeSchema;
    using Microsoft.VisualStudio.ArchitectureTools.Extensibility.Layer;
    using Microsoft.VisualStudio.GraphModel;
    ...
    [Export(typeof(IValidateArchitectureExtension))]
      public partial class Validator1Extension :
                      IValidateArchitectureExtension
      {
        public void ValidateArchitecture(Graph graph)
        {
           GraphSchema schema = graph.DocumentSchema;
          ...
      } }
    
  • Ao descobrir um erro, você pode reportá-lo usando LogValidationError().

    Aviso

    Não use os parâmetros opcionais de LogValidationError.

Quando o usuário chama o comando de menu Validar arquitetura, o sistema de runtime de camada analisa as camadas e seus artefatos para produzir um grafo. O grafo tem quatro partes:

  • Modelos de camada da solução do Visual Studio representados como nós e links no grafo.

  • Código, itens de projeto e outros artefatos definidos na solução e representados como nós e links que representam as dependências descobertas pelo processo de análise.

  • Links dos nós de camada para os nós de artefato de código.

  • Nós que representam erros descobertos pelo validador.

Quando o grafo é construído, o método de validação padrão é chamado. Quando é concluído, todos os métodos de validação de extensão instalados são chamados em ordem não especificada. O grafo é passado para cada método ValidateArchitecture, que pode examinar o grafo e relatar quaisquer erros encontrados.

Observação

Não é o mesmo que o processo de validação que pode ser usado em linguagem específica de domínio.

Os métodos de validação não devem alterar o modelo de camada ou o código que está sendo validado.

O modelo de grafo é definido em Microsoft.VisualStudio.GraphModel. Suas classes principais são GraphNode e GraphLink.

Cada Nó e cada Link tem uma ou mais Categorias que especificam o tipo de elemento ou relação representado. Os nós de um grafo normal têm as seguintes categorias:

  • Dsl.LayerModel

  • Dsl.Layer

  • Dsl.Reference

  • CodeSchema_Type

  • CodeSchema_Namespace

  • CodeSchema_Type

  • CodeSchema_Method

  • CodeSchema_Field

  • CodeSchema_Property

Os links de camadas para elementos no código têm a categoria "Representa".

Validação de depuração

Para depurar a extensão de validação de camada, pressione CTRL+F5. Uma instância experimental do Visual Studio é aberta. Nessa instância, abra ou crie um modelo de camada. Esse modelo deve ser associado ao código e deve ter pelo menos uma dependência.

Testar com uma solução que contém dependências

A validação não é executada, a menos que existam as seguintes características:

  • Há pelo menos um link de dependência no diagrama de dependência.

  • Há camadas no modelo associadas a elementos de código.

Na primeira vez que iniciar uma instância experimental do Visual Studio para testar sua extensão de validação, abra ou crie uma solução que tenha essas características.

Executar a solução limpa antes de validar a arquitetura

Sempre que você atualizar o código de validação, use o comando Limpar Solução no menu Compilar na solução experimental antes de testar o comando Validar. É necessário porque os resultados da validação são armazenados em cache. Se não tiver atualizado o diagrama de dependência de teste ou seu código, os métodos de validação não serão executados.

Iniciar o depurador explicitamente

A validação é executada em um processo separado. Portanto, os pontos de interrupção em seu método de validação não serão disparados. Você deve anexar o depurador ao processo explicitamente quando a validação for iniciada.

Para anexar o depurador ao processo de validação, insira uma chamada para System.Diagnostics.Debugger.Launch() no início do método de validação. Quando a caixa de diálogo de depuração for exibida, selecione a instância principal do Visual Studio.

Como alternativa, é possível inserir uma chamada para System.Windows.Forms.MessageBox.Show(). Quando a caixa de mensagem for exibida, vá para a instância principal do Visual Studio e, no menu Depurar, clique em Anexar ao Processo. Selecione o processo chamado Graphcmd.exe.

Sempre inicie a instância experimental pressionando CTRL+F5 (Iniciar sem Depuração).

Implantando uma extensão de validação

Para instalar sua extensão de validação em um computador no qual uma versão adequada do Visual Studio está instalada, abra o arquivo VSIX no computador de destino.

Código de exemplo

using System;
using System.ComponentModel.Composition;
using System.Globalization;
using System.Linq;
using System.Text.RegularExpressions;
using Microsoft.VisualStudio.ArchitectureTools.Extensibility.CodeSchema;
using Microsoft.VisualStudio.ArchitectureTools.Extensibility.Layer;
using Microsoft.VisualStudio.GraphModel;

namespace Validator3
{
    [Export(typeof(IValidateArchitectureExtension))]
    public partial class Validator3Extension : IValidateArchitectureExtension
    {
        /// <summary>
        /// Validate the architecture
        /// </summary>
        /// <param name="graph">The graph</param>
        public void ValidateArchitecture(Graph graph)
        {
            if (graph == null) throw new ArgumentNullException("graph");

            // Uncomment the line below to debug this extension during validation
            // System.Windows.Forms.MessageBox.Show("Attach 2 to GraphCmd.exe with process id " + System.Diagnostics.Process.GetCurrentProcess().Id);

            // Get all layers on the diagram
            foreach (GraphNode layer in graph.Nodes.GetByCategory("Dsl.Layer"))
            {
                System.Threading.Thread.Sleep(100);
                // Get the required regex property from the layer node
                string regexPattern = "^[a-zA-Z]+$"; //layer[customPropertyCategory] as string;
                if (!string.IsNullOrEmpty(regexPattern))
                {
                    Regex regEx = new Regex(regexPattern);

                    // Get all referenced types in this layer including those from nested layers so each
                    // type is validated against all containing layer constraints.
                    foreach (GraphNode containedType in layer.FindDescendants().Where(node => node.HasCategory("CodeSchema_Type")))
                    {
                        // Check the type name against the required regex
                        CodeGraphNodeIdBuilder builder = new CodeGraphNodeIdBuilder(containedType.Id, graph);
                        string typeName = builder.Type.Name;
                        if (!regEx.IsMatch(typeName))
                        {
                            // Log an error
                            string message = string.Format(CultureInfo.CurrentCulture, Resources.InvalidTypeNameMessage, typeName);
                            this.LogValidationError(graph, typeName + "TypeNameError", message, GraphErrorLevel.Error, layer);
                        }
                    }
                }

            }

        }
    }
}