Como: Definir restrições de validação dos modelos UML

Em Visual Studio Ultimate, você pode definir restrições de validação para testar se o modelo atende a uma condição especificada. Por exemplo, você poderia definir uma restrição para certificar-se de que um usuário não cria um loop de relações de herança. A restrição é chamada quando o usuário tenta abrir ou salvar o modelo e também pode ser chamado manualmente. Se a restrição falhar, uma mensagem de erro que você define é adicionada à janela de erro. Você pode empacotar essas restrições em um Visual Studio a extensão de integração (VSIX) e distribuí-lo a outros Visual Studio Ultimate os usuários.

Você também pode definir restrições de validar o modelo em relação a recursos externos como, por exemplo, bancos de dados.

ObservaçãoObservação

Se você deseja validar código de programa em relação a um diagrama de camada, consulte Adicionar validação de arquitetura de personalizada aos diagramas de camada.

Requisitos

Aplicação de restrições de validação

Restrições de validação são aplicadas em três casos: Quando você salva um modelo; Quando você abre um modelo; e quando você clica em Validar o modelo de UML sobre o arquitetura menu. Em cada caso, somente aqueles que foram definidas para esse caso restrições serão aplicadas, embora normalmente você definiria cada restrição para aplicar mais de um caso.

Erros de validação são relatados no Visual Studio janela de erros e você pode clicar duas vezes o erro para selecionar os elementos de modelo que estão em erro.

Para obter mais informações sobre a aplicação de validação, consulte Como: Validar um modelo UML.

A definição de uma extensão de validação

Para criar uma extensão de validação para um designer UML, você deve criar uma classe que define as restrições de validação e incorporar a classe em um Visual Studio integração extensão (VSIX). O VSIX atua como um recipiente que pode instalar a restrição. Há dois métodos alternativos de definição de uma extensão de validação:

  • Crie uma extensão de validação em seu próprio VSIX usando um modelo de projeto. Este é o método mais rápido. Usá-lo se você não deseja combinar as restrições de validação com outros tipos de extensão como, por exemplo, comandos de menu, itens de caixa de ferramentas personalizada, ou manipuladores de gesto. Você pode definir várias restrições em uma classe.

  • Crie projetos VSIX e classe separada de validação. Use este método se você deseja combinar vários tipos de extensão para o mesmo VSIX. Por exemplo, se o comando de menu espera o modelo para observar as restrições específicas, você pode incorporá-lo no mesmo VSIX como um método de validação.

Para criar uma extensão de validação em seu próprio VSIX

  1. No Novo projeto caixa de diálogo, em Projetos de modelagem, selecione A extensão de validação.

  2. Abrir o .cs arquivo no novo projeto e modificar a classe para implementar a restrição de validação.

    Para obter mais informações, consulte implementar a restrição de validação.

  3. Você pode adicionar restrições adicionais definindo novos métodos. Para identificar um método como um método de validação, ele deve ser marcado com os atributos da mesma forma como o método de validação inicial.

  4. Teste suas restrições, pressionando F5. Para obter mais informações, consulte Executar validação.

  5. Instalar o comando de menu em outro computador, copiando o arquivo bin\*\*.vsix que é criado pelo projeto. Para obter mais informações, consulte Instalando as restrições de validação.

Para criar uma restrição de validação separados em um projeto de biblioteca de classe

  1. Crie um projeto de biblioteca de classe, adicioná-lo em uma solução VSIX existente ou criar uma nova solução.

    1. No menu File, aponte para New e clique Project.

    2. Em Modelos instalados, clique em C# Visual ou Visual Basic, em seguida, na coluna do meio, clique em Biblioteca de classe.

    3. Definir solução para indicar se você deseja criar uma nova solução ou para adicionar um componente a uma solução VSIX que você já tiver aberto.

    4. Definir o projeto de nome e local e clique em OK.

  2. A menos que sua solução já contém um, crie um projeto VSIX.

    1. Em Solution Explorer, a solução com o botão direito, aponte para Adde em seguida, clique em Novo projeto.

    2. Em Modelos instalados, expanda Visual C# ou Visual Basic, em seguida, clique em extensibilidade. Na coluna do meio, clique em O projeto de VSIX.

  3. Defina o projeto VSIX como o projeto de inicialização da solução.

    • No Solution Explorer, clique com o botão direito no projeto VSIX e clique em Set as StartUp project.
  4. Em source.extension.vsixmanifest, em conteúdo, adicione o projeto de biblioteca de classe como um componente de MEF.

    1. Abrirsource.extension.vsixmanifest

    2. Clique em Adicionar conteúdo.

    3. Em Selecione um tipo de conteúdo, selecione MEF componente.

    4. Em Selecionar uma fonte de, clique em projeto e selecione o nome do seu projeto de biblioteca de classe.

  5. Clique em Selecione edições e selecione o Visual Studio edições você deseja que sua extensão a ser executada.

  6. Defina o nome e os campos descritivos do VSIX. Salve o arquivo.

Para definir a classe de validação

  1. Esse procedimento não é necessário se você tiver criado uma classe de validação com sua própria VSIX de modelo de projeto de validação.

  2. No projeto de classe de validação, adicionar referências para o seguinte .NET assemblies:

    Microsoft.VisualStudio.Modeling.Sdk.10.0

    Microsoft.VisualStudio.ArchitectureTools.Extensibility.Uml

    Microsoft.VisualStudio.Uml.Interfaces

    System.ComponentModel.Composition

  3. Adicione um arquivo ao projeto de biblioteca de classe que contém o código que é semelhante ao exemplo a seguir.

    • Cada restrição de validação está contida dentro de um método marcado com um atributo específico. O método aceita um parâmetro de um tipo de elemento de modelo. Quando a validação é chamada, a estrutura de validação serão aplicadas a cada método de validação para cada elemento de modelo que está de acordo com seu tipo de parâmetro.

    • Você pode colocar esses métodos em qualquer classes e namespaces. Para alterá-los para a sua preferência.

    using System.Collections.Generic;
    using System.ComponentModel.Composition;
    using System.Linq;
    using Microsoft.VisualStudio.Modeling.Validation;
    using Microsoft.VisualStudio.ArchitectureTools.Extensibility.Uml;
    using Microsoft.VisualStudio.Uml.Classes;
    // You might also need the other Microsoft.VisualStudio.Uml namespaces.
    
    namespace Validation
    {
      public class MyValidationExtensions
      {
        // SAMPLE VALIDATION METHOD.
        // All validation methods have the following attributes.
        [Export(typeof(System.Action<ValidationContext, object>))]
        [ValidationMethod(
           ValidationCategories.Save
         | ValidationCategories.Open
         | ValidationCategories.Menu)]
        public void ValidateClassNames
          (ValidationContext context, 
           // This type determines what elements 
           // will be validated by this method:
           IClass elementToValidate)
        {
          // A validation method should not change the model.
    
          List<string> attributeNames = new List<string>();
          foreach (IProperty attribute in elementToValidate.OwnedAttributes)
          {
            string name = attribute.Name;
            if (!string.IsNullOrEmpty(name) && attributeNames.Contains(name))
            {
              context.LogError(
                string.Format("Duplicate attribute name '{0}' in class {1}", name, elementToValidate.Name),
                "001", elementToValidate);
            }
            attributeNames.Add(name);
          }
    
        }
        // Add more validation methods for different element types.
      }
    }
    

A execução de uma restrição de validação

Para fins de teste execute seus métodos de validação no modo de depuração.

Para testar a restrição de validação

  1. Pressione F5, ou de Debug menu, clique em Start Debugging.

    Uma instância experimental do Visual Studio é iniciado.

    Solucionando problemas de: Se uma nova Visual Studio não iniciado:

    • Se você tiver mais de um projeto, certifique-se de que o projeto VSIX é definido como o projeto de inicialização da solução.

    • No Solution Explorer, clique com o botão direito na inicialização ou somente projeto e clique em Propriedades. No editor de propriedades do projeto, clique na Debug guia. Certifique-se de que a seqüência de caracteres de Start external program campo é o caminho completo do Visual Studio, normalmente:

      10.0\Common7\IDE\devenv.exe do c:\Arquivos de Programas\Microsoft Visual Studio

  2. No experimental Visual Studio, abra ou crie um projeto de modelagem e abrir ou criar um diagrama de modelagem.

  3. Para configurar um teste para a restrição de exemplo fornecida na seção anterior:

    1. Abra um diagrama de classe.

    2. Criar uma classe e adicionar dois atributos têm o mesmo nome.

  4. Clique com o botão direito em qualquer lugar no diagrama e, em seguida, clique em Validar.

  5. Quaisquer erros no modelo serão informados na janela de erros.

  6. Clique duas vezes no relatório de erros. Se os elementos mencionados no relatório são visíveis na tela, elas serão realçadas.

    Solucionando problemas de: Se o Validar comando não aparecer no menu, certifique-se de que:

    • O projeto de validação é listado como um componente MEF a conteúdo Listar no source.extensions.manifest no projeto VSIX.

    • O correto Export e ValidationMethod atributos associados a métodos de validação.

    • ValidationCategories.Menuestá incluído no argumento para o ValidationMethod atributo e ele é composto com outros valores usando lógica OR (|).

    • Os parâmetros de todos os Import e Export atributos são válidos.

Avaliando a restrição

O método de validação deve determinar se a restrição de validação que você deseja aplicar é verdadeiro ou falso. Se verdadeiro, ele deve fazer nada. Se false, ele deverá relatar um erro usando os métodos fornecidos pelo ValidationContext parâmetro.

ObservaçãoObservação

Métodos de validação não devem alterar o modelo. Há nenhuma garantia quando ou em qual ordem que as restrições serão executadas. Se você tiver passam informações entre as execuções sucessivas de um método de validação dentro de uma execução de validação, você pode usar o cache de contexto descrito em Coordenando várias validações.

Por exemplo, se você quiser garantir que cada tipo (classe, interface ou enumerador) tem um nome que tenha pelo menos três caracteres, você poderia usar esse método:

public void ValidateTypeName(ValidationContext context, IType type)
{
  if (!string.IsNullOrEmpty(type.Name) && type.Name.Length < 3)
  {
    context.LogError(
      string.Format("Type name {0} is too short", type.Name),
               "001", type);
   }
 }

Consulte Programação com a API de UML para obter informações sobre os métodos e tipos podem ser usados para navegar e ler o modelo.

Sobre métodos de restrição de validação

Cada restrição de validação é definida por um método da seguinte forma:

[Export(typeof(System.Action<ValidationContext, object>))]
 [ValidationMethod(ValidationCategories.Save 
  | ValidationCategories.Menu 
  | ValidationCategories.Open)]
public void ValidateSomething
  (ValidationContext context, IClassifier elementToValidate)
{...}

Os atributos e parâmetros de cada método de validação são:

[Export(typeof(System.Action <ValidationContext, object>))]

Define o método como uma restrição de validação usando o Managed Extensibility Framework (MEF).

[ValidationMethod (ValidationCategories.Menu)]

Especifica quando a validação será executada. OR bit a bit de uso (|), se você deseja combinar mais de uma opção.

Menu= invocado pelo menu validar.

Save= invocada salvando o modelo.

Open= invocado na abertura do modelo. Load= chamado como salvar o modelo, mas para uma contravenção avisa ao usuário que talvez não seja possível reabrir o modelo. Também é chamado em carregar, antes que o modelo seja analisado.

public void ValidateSomething

(ValidationContext context,

IElement element)

Substitua o segundo parâmetro IElement pelo tipo de elemento ao qual você deseja aplicar a restrição. O método de restrição será chamado em todos os elementos do tipo especificado.

O nome do método não é importante.

Você pode definir métodos de validação tantas quantas desejar, com diferentes tipos no segundo parâmetro. Quando a validação é chamada, cada método de validação será chamado em cada elemento de modelo que está de acordo com o tipo de parâmetro.

Relatar erros de validação

Para criar um relatório de erro, use os métodos fornecidos pelo ValidationContext:

context.LogError("error string", errorCode, elementsWithError);

  • "error string"consta a Visual Studio Error List

  • errorCodeé uma seqüência de caracteres deve ser um identificador exclusivo do erro

  • elementsWithErroridentifica os elementos no modelo. Quando o usuário clica duas vezes no relatório de erros, a forma que representa esse elemento será selecionada.

LogError(), LogWarning()e LogMessage() colocar mensagens em diferentes seções de lista de erro.

Como os métodos de validação são aplicados

Validação é aplicada a todos os elementos de modelo, incluindo as relações e partes de elementos maiores, como, por exemplo, os atributos de uma classe e os parâmetros de uma operação.

Cada método de validação é aplicado a cada elemento que está de acordo com o tipo de seu segundo parâmetro. Isso significa que, por exemplo, se você definir um método de validação com um segundo parâmetro do IUseCase e outra com seu supertipo IElement, em seguida, esses dois métodos serão aplicados a cada caso de uso do modelo.

A hierarquia de tipos é resumida na Tipos de elemento de modelo.

Você também pode acessar os elementos seguindo relações. Por exemplo, se você definir um método de validação em IClass, você poderia fazer um loop através de suas propriedades pertencente a:

public void ValidateTypeName(ValidationContext context, IClass c)
{
   foreach (IProperty property in c.OwnedAttributes)
   {
       if (property.Name.Length < 3)
       {
            context.LogError(
                 string.Format(
                        "Property name {0} is too short", 
                        property.Name), 
                 "001", property);
        }
   }
}

Criar um método de validação no modelo

Se você deseja garantir que um método de validação é chamado de exatamente uma vez durante cada execução de validação, você pode validar o IModel:

using Microsoft.VisualStudio.Uml.AuxiliaryConstructs; ...
[Export(typeof(System.Action<ValidationContext, object>))]
[ValidationMethod(ValidationCategories.Menu)]
public void ValidateModel(ValidationContext context, IModel model)
{  foreach (IElement element in model.OwnedElements)
   { ...

Validando as formas e diagramas

Métodos de validação não são invocados em elementos de exibição como, por exemplo, diagramas e formas, porque o objetivo principal dos métodos de validação é validar o modelo. Mas você pode acessar o diagrama atual usando o contexto do diagrama.

Na sua classe de validação, declarar DiagramContext como uma propriedade importada:

using Microsoft.VisualStudio.ArchitectureTools.Extensibility.Presentation; 
...
[Import]
public IDiagramContext DiagramContext { get; set; }

Em um método de validação, você pode usar DiagramContext para acessar o diagrama de foco atual, se houver um:

[Export(typeof(System.Action<ValidationContext, object>))]
[ValidationMethod(ValidationCategories.Menu)]
public void ValidateModel(ValidationContext context, IModel model)
{
  IDiagram focusDiagram = DiagramContext.CurrentDiagram;
  if (focusDiagram != null)
  {
    foreach (IShape<IUseCase> useCaseShape in
              focusDiagram.GetChildShapes<IUseCase>())
    { ...

Para registrar um erro, você deve obter o elemento de modelo que representa a forma, porque você não pode passar de uma forma para LogError:

       IUseCase useCase = useCaseShape.Element;
       context.LogError(... , usecase);

Coordenação de várias validações

Quando a validação é chamada, por exemplo pelo usuário em um menu de diagrama, cada método de validação é aplicado a cada elemento de modelo. Isso significa que, em uma única invocação de estrutura de validação, o mesmo método pode ser aplicado muitas vezes a elementos diferentes.

Isso apresenta um problema para validações que lidam com as relações entre elementos. Por exemplo, você pode escrever uma validação que inicia a partir de, digamos, um caso de uso e percorre o include para verificar se há os relacionamentos são sem loops. Mas quando o método é aplicado para cada caso de uso de um modelo que tenha muitos include links, é provável que repetidamente processar as mesmas áreas do modelo.

Para evitar essa situação, há um cache de contexto no qual as informações são preservadas durante uma execução de validação. Você pode usá-lo para passar informações entre as execuções diferentes dos métodos de validação. Por exemplo, você poderia armazenar uma lista dos elementos que já tenha sido lidado com na execução de validação. O cache é criado no início de cada execução de validação e não pode ser usado para passar informações entre as execuções de validação diferentes.

context.SetCacheValue<T> (name, value)

Armazenar um valor

context.TryGetCacheValue<T> (name, out value)

Obter um valor. Retorna true se for bem-sucedido.

context.GetValue<T>(name)

Obter um valor.

Context.GetValue<T>()

Obter um valor do tipo especificado.

Instalar e desinstalar uma extensão.

Você pode instalar um Visual Studio extensão em seu próprio computador e em outros computadores.

Para instalar uma extensão.

  1. No seu computador, localize o .vsix arquivo que foi criado pelo seu projeto VSIX.

    1. Em Solution Explorer, o botão direito do mouse no projeto VSIX e em Abrir a pasta no Windows Explorer.

    2. Localize o arquivo bin\*\YourProject.vsix

  2. Cópia de .vsix o arquivo para o computador de destino no qual você deseja instalar a extensão. Isso pode ser o seu próprio computador ou outro.

    • O computador de destino deve ter uma das edições do Visual Studio que você especificou na source.extension.vsixmanifest.
  3. No computador de destino, clique duas vezes o .vsix arquivo.

    Instalador de extensão de Visual Studio abre e instala a extensão.

  4. Iniciar ou reiniciar Visual Studio.

Para desinstalar uma extensão.

  1. Sobre o Ferramentas menu, clique em Extension Manager.

  2. Expanda as extensões instaladas.

  3. Selecione a extensão e clique em desinstalar.

Raramente, uma extensão com defeito não consegue carregar e cria um relatório na janela de erros, mas não aparece no Gerenciador de extensão. Nesse caso, você pode remover a extensão, excluindo o arquivo do seguinte local onde % LocalAppData % é normalmente Nome_da_unidade: \Users\nome de usuário\AppData\Local:

% LocalAppData %\Microsoft\VisualStudio\10.0\Extensions

Exemplo

Este exemplo localiza loops na relação de dependência entre elementos.

Ele irá validar ambos salvar e no comando de menu ' Validar '.

/// <summary>
/// Verify that there are no loops in the dependency relationsips.
/// In our project, no element should be a dependent of itself.
/// </summary>
/// <param name="context">Validation context for logs.</param>
/// <param name="element">Element to start validation from.</param>
[Export(typeof(System.Action<ValidationContext, object>))]
[ValidationMethod(ValidationCategories.Menu 
     | ValidationCategories.Save | ValidationCategories.Open)]
public void NoDependencyLoops(ValidationContext context, INamedElement element)
{
    // The validation framework will call this method
    // for every element in the model. But when we follow
    // the dependencies from one element, we will validate others.
    // So we keep a list of the elements that we don't need to validate again. 
    // The list is kept in the context cache so that it is passed
    // from one execution of this method to another.
    List<INamedElement> alreadySeen = null;
    if (!context.TryGetCacheValue("No dependency loops", out alreadySeen))
    {
       alreadySeen = new List<INamedElement>();
       context.SetCacheValue("No dependency loops", alreadySeen);
    }

    NoDependencyLoops(context, element, 
                new INamedElement[0], alreadySeen);    
}

/// <summary>
/// Log an error if there is any loop in the dependency relationship.
/// </summary>
/// <param name="context">Validation context for logs.</param>
/// <param name="element">The element to be validated.</param>
/// <param name="dependants">Elements we've followed in this recursion.</param>
/// <param name="alreadySeen">Elements that have already been validated.</param>
/// <returns>true if no error was detected</returns>
private bool NoDependencyLoops(ValidationContext context, 
    INamedElement element, INamedElement[] dependants, 
    List<INamedElement> alreadySeen)
{
    if (dependants.Contains(element))
    {
        context.LogError(string.Format("{0} should not depend on itself", element.Name), 
        "Fabrikam.UML.NoGenLoops", // unique code for this error
        dependants.SkipWhile(e => e != element).ToArray()); 
            // highlight elements that are in the loop
        return false;
    }
    INamedElement[] dependantsPlusElement = 
        new INamedElement[dependants.Length + 1];
    dependants.CopyTo(dependantsPlusElement, 0);
    dependantsPlusElement[dependantsPlusElement.Length - 1] = element;

    if (alreadySeen.Contains(element))
    {
        // We have already validated this when we started 
        // from another element during this validation run.
        return true;
    }
    alreadySeen.Add(element);

    foreach (INamedElement supplier in element.GetDependencySuppliers())
    {
        if (!NoDependencyLoops(context, supplier,
             dependantsPlusElement, alreadySeen))
        return false;
    }
    return true;
}

Consulte também

Conceitos

Programação com a API de UML

Outros recursos

Como: Definir e instalar uma extensão de modelagem