Como: Gerar arquivos a partir de um modelo UML

A partir de um modelo UML, você pode gerar código de programa, esquemas, documentos, recursos e outros artefatos de qualquer tipo. Um método conveniente para gerar arquivos de texto de um modelo UML é usar modelos de texto. Elas permitem que você incorpore o código de programa dentro do texto que você deseja gerar.

Há três cenários principais:

  • Gerando arquivos de um comando de menu ou gesto. Você pode definir um Visual Studio comando que está disponível em modelos UML.

  • Gerando arquivos de um aplicativo. Você escrever um aplicativo que lê os modelos UML e gera arquivos.

  • Gerando em tempo de design. Você usar um modelo para definir alguns itens da funcionalidade do aplicativo e gerar código, recursos, e assim por diante, dentro do Visual Studio solução.

Este tópico termina com uma discussão de como usar a geração de texto. Para obter mais informações, consulte Modelos de texto T4 e de geração de código.

Gerando arquivos de um comando de menu

Você pode usar pré-processar modelos de texto dentro de um comando de menu UML. Dentro do código do modelo de texto ou em uma classe parcial separada, você pode ler o modelo que será exibido pelo diagrama.

Para obter mais informações sobre esses recursos, leia os tópicos a seguintes:

A abordagem demonstrada no exemplo a seguir é adequada para gerar o texto de um único modelo, quando você inicia a operação de um dos diagramas de modelo. Para processar um modelo em um contexto separado, considere o uso de Visual Studio Modelbus de para acessar o modelo e seus elementos.

Exemplo

Para executar esse exemplo, crie um Visual Studio (VSIX) de extensão de projeto. O nome do projeto é usado neste exemplo é VdmGenerator. No source.extension.vsixmanifest de arquivo, clique em Adicionar conteúdo e defina o campo de tipo MEF componente e o caminho de origem, fazendo referência ao projeto atual. Para obter mais informações sobre como configurar esse tipo de projeto, consulte Como: Definir um comando de Menu em um diagrama de modelagem.

Adicione um arquivo de C# que contém o seguinte código ao projeto. Essa classe define um comando de menu que será exibido em um diagrama de classe UML.

using System;
using System.ComponentModel.Composition;
using Microsoft.VisualStudio.ArchitectureTools.Extensibility.Uml;
using Microsoft.VisualStudio.ArchitectureTools.Extensibility.Presentation;
using Microsoft.VisualStudio.Modeling.ExtensionEnablement;

namespace VdmGenerator
{
  [Export(typeof(ICommandExtension))]
  [ClassDesignerExtension]
  public class GenerateVdmFromClasses : ICommandExtension
  {
    [Import] public IDiagramContext DiagramContext { get; set; }
    public void Execute(IMenuCommand command)
    {
      // Initialize the template with the Model Store.
      VdmGen generator = new VdmGen(
             DiagramContext.CurrentDiagram.ModelStore);
      // Generate the text and write it.
      System.IO.File.WriteAllText
        (System.IO.Path.Combine(
            Environment.GetFolderPath(
                Environment.SpecialFolder.Desktop),
            "Generated.txt") 
         , generator.TransformText());
    }
    public void QueryStatus(IMenuCommand command)
    {
      command.Enabled = command.Visible = true;
    }
    public string Text
    { get { return "Generate VDM"; } }
  }
}

O arquivo a seguir é o modelo de texto. Ele gera uma linha de texto para cada classe UML no modelo e uma linha para cada atributo em cada classe. O código para leitura, o modelo é incorporado no texto, delimitado por <# ... #>.

Para criar esse arquivo, clique com o botão direito no projeto no Solution Explorer, aponte para Adde em seguida, clique em Novo Item. Selecione pré-processado o modelo de texto. O nome de arquivo para este exemplo deve ser VdmGen.tt. O Ferramenta personalizada a propriedade do arquivo deve ser TextTemplatingFilePreprocessor. Para obter mais informações sobre modelos de texto pré-processado, consulte Geração de texto de tempo de execução usando os modelos de texto T4.

<#@ import namespace="Microsoft.VisualStudio.Uml.Classes" #>
<# 
   foreach (IClass classElement in store.AllInstances<IClass>())
   {
#>
Type <#= classElement.Name #> ::
<#
     foreach (IProperty attribute in classElement.OwnedAttributes)
     {
#>
       <#= attribute.Name #> : <#= 
           attribute.Type == null ? ""
                                  : attribute.Type.Name #> 
<#
     }
   }
#>

O modelo de texto gera uma C# classe parcial, que se torna parte de sua Visual Studio project. Em um arquivo separado, adicione outra declaração parcial da mesma classe. Esse código fornece o modelo com acesso ao armazenamento de modelo UML:

using Microsoft.VisualStudio.ArchitectureTools.Extensibility.Uml;
namespace VdmGenerator
{
    public partial class VdmGen
    {
        private IModelStore store;
        public VdmGen(IModelStore s)
        { store = s; }
    }
}

Para testar o projeto, pressione F5. Uma nova instância de Visual Studio irá iniciar. Neste exemplo, abrir ou criar um modelo UML que contém um diagrama de classe. Adicionar algumas classes ao diagrama e adicione alguns atributos para cada classe. Clique com o botão direito no diagrama e, em seguida, clique no comando de exemplo Gerar VDM. O comando cria o arquivo C:\Generated.txt. Inspecione a esse arquivo. Seu conteúdo deve se parecer com o seguinte texto, mas ele irá listar suas próprias classes e atributos:

Type Class1 ::
          Attribute1 : int 
          Attribute2 : string 
Type Class2 :: 
          Attribute3 : string 

Gerando arquivos de um aplicativo

Você pode gerar arquivos de um aplicativo que lê um modelo UML. Para essa finalidade, é o método mais flexível e robusto de acessar o modelo e seus elementos Visual Studio Modelbus de.

Você também pode usar a API básica para carregar o modelo e passar o modelo para os modelos de texto usando as mesmas técnicas como na seção anterior. Para obter mais informações sobre como carregar um modelo, consulte Como: Um modelo UML no código do programa de leitura..

Gerando arquivos em tempo de Design

Se seu projeto possui um método padrão de interpretar UML como código, você pode criar modelos de texto que permitem gerar código dentro de seu projeto a partir de um modelo UML. Normalmente, você teria uma solução que contém o projeto de modelo UML e um ou mais projetos para o código do aplicativo. Cada projeto de código pode conter vários modelos que geram arquivos de código, recursos e configuração do programa, com base no conteúdo do modelo. O desenvolvedor pode executar todos os modelos clicando no Transformar todos os modelos de na barra de ferramentas do Solution Explorer. Geralmente, o código de programa é gerado na forma de classes parciais, para facilitar a integrar partes escrito manualmente.

A Visual Studio projeto desse tipo pode ser distribuído na forma de um modelo, para que todos os membros de uma equipe é capaz de criar projetos que geram um código de um modelo na mesma maneira. Normalmente, o modelo é parte de um pacote de extensão que inclui as restrições de validação no modelo para garantir que as pré-condições do código de geração são atendidas.

Procedimento para gerar arquivos de estrutura de tópicos

  • Para adicionar um modelo para um projeto, selecione O modelo de texto na caixa de diálogo Adicionar novo arquivo. Você pode adicionar um modelo para a maioria dos tipos de projeto, mas não os projetos de modelagem.

  • A propriedade personalizada de ferramentas do arquivo de modelo deve ser TextTemplatingFileGenerator, e a extensão de nome de arquivo deve ser .tt.

  • O modelo deve ter pelo menos uma diretiva de saída:

    <#@ output extension=".cs" #>

    Defina o campo de extensão de acordo com o idioma do seu projeto.

  • Para permitir a gerar código em seu modelo para acessar o modelo, escrever <#@ assembly #> diretivas para os assemblies necessários para ler um modelo UML. Use ModelingProject.LoadReadOnly() para abrir o modelo. Para obter mais informações, consulte Como: Um modelo UML no código do programa de leitura..

  • O modelo é executado quando você salvar e quando você clica em Transformar todos os modelos de na barra de ferramentas do Solution Explorer.

  • Para obter mais informações sobre este tipo de modelo, consulte Geração de código de tempo de design usando modelos de texto T4.

  • Um projeto típico, você terá vários modelos que geram arquivos diferentes do mesmo modelo. A primeira parte de cada modelo será o mesmo. Para reduzir essa duplicação, mover as partes comuns para um arquivo de texto separado e, em seguida, chamá-la usando a diretiva <#@include file="common.txt"#> em cada modelo.

  • Você também pode definir um processador de diretriz especializado que permite que você fornecer parâmetros para o processo de geração de texto. Para obter mais informações, consulte Personalizando a transformação de texto T4.

Exemplo

Este exemplo gera uma classe C# para cada classe UML no modelo de origem.

Para configurar uma solução para esse exemplo de Visual Studio

  1. Crie um diagrama de classe UML em um projeto de modelagem em uma nova solução.

    1. No arquitetura menu, clique em Novo diagrama.

    2. Selecione diagrama de classe UML.

    3. Siga os prompts para criar um novo projeto de solução e modelagem.

    4. Adicione algumas classes ao diagrama arrastando a ferramenta de classe UML do toolbox.

    5. Salve o arquivo.

  2. Crie um projeto de C# ou Visual Basic na mesma solução.

    • No Solution Explorer, clique com o botão direito a solução, aponte para Adde em seguida, clique em Novo projeto. Em Modelos instalados, clique em Visual Basic ou Visual C#, e, em seguida, selecione um tipo de projeto, como Aplicativo de Console.
  3. Adicione um arquivo de texto sem formatação para o C# ou Visual Basic de projeto. Esse arquivo irá conter o código compartilhado se desejar gravar vários modelos de texto.

    • No Solution Explorer, clique com o botão direito no projeto, aponte para Adde em seguida, clique em Novo Item. Selecione arquivo de texto.

    Insira o texto que é mostrado na seção a seguir.

  4. Adicione um arquivo de modelo de texto para o C# ou Visual Basic de projeto.

    • No Solution Explorer, clique com o botão direito no projeto, aponte para Adde em seguida, clique em Novo Item. Selecione o modelo de texto.

    Insira o código a seguir no arquivo de modelo de texto.

  5. Salve o arquivo de modelo de texto.

  6. Inspecione o código no arquivo da subsidiária. Ele deve conter uma classe para cada classe UML no modelo.

    1. Em um projeto de Visual Basic, clique em Mostrar todos os arquivos na barra de ferramentas do Solution Explorer.

    2. Expanda o nó do arquivo de modelo no Solution Explorer.

Conteúdo do arquivo de texto compartilhado

Neste exemplo, o arquivo é chamado SharedTemplateCode.txt e ele está na mesma pasta em que os modelos de texto.

<# /* Common material for inclusion in my model templates */ #>
<# /* hostspecific allows access to the Visual Studio API */ #>
<#@ template debug="false" hostspecific="true" language="C#" #>
<#@ assembly name="Microsoft.VisualStudio.Uml.Interfaces.dll"#>
<#@ assembly name="Microsoft.VisualStudio.ArchitectureTools.Extensibility.dll"#>
<#@ assembly name="EnvDTE" #>
<#@ import namespace="Microsoft.VisualStudio.Uml.Classes" #>
<#@ import namespace="Microsoft.VisualStudio.ArchitectureTools.Extensibility" #>
<#@ import namespace="Microsoft.VisualStudio.ArchitectureTools.Extensibility.Uml" #>
<#+  // Note this is a Class Feature Block
///<summary>
/// Text templates are run in a common AppDomain, so 
/// we can cache the model store that we find.
///</summary>
private IModelStore StoreCache
{
  get { return AppDomain.CurrentDomain.GetData("ModelStore") as IModelStore; }
  set { AppDomain.CurrentDomain.SetData("ModelStore", value); } 
}
private bool CacheIsOld()
{
    DateTime? dt = AppDomain.CurrentDomain
           .GetData("latestAccessTime") as DateTime?;
    DateTime t = dt.HasValue ? dt.Value : new DateTime(); 
    DateTime now = DateTime.Now;
    AppDomain.CurrentDomain.SetData("latestAccessTime", now);
    return now.Subtract(t).Seconds > 3;
}

///<summary>
/// Find the UML modeling project in this solution,
/// and load the model.
///</summary>
private IModelStore ModelStore
{
  get 
  {
    // Avoid loading the model for every template:
    if (StoreCache == null || CacheIsOld())
    {
      // Use Visual Studio API to find modeling project:
      EnvDTE.DTE dte = (EnvDTE.DTE) ((IServiceProvider) this.Host)
                       .GetService(typeof(EnvDTE.DTE));
      EnvDTE.Project project = null;
      foreach (EnvDTE.Project p in dte.Solution.Projects)
      {
        if (p.FullName.EndsWith(".modelproj"))
        {
          project = p;
          break;
        }            
      }
      if (project == null) return null;

      // Load UML model into this AppDomain
      // and access model store:
      IModelingProjectReader reader = 
           ModelingProject.LoadReadOnly(project.FullName);
      StoreCache = reader.Store;
    }
    return StoreCache;
  }
}
#>

Conteúdo do arquivo de modelo de texto

O seguinte texto é colocado no .tt arquivo. Este exemplo gera classes em um arquivo de C# de classes UML no modelo. No entanto, você pode gerar arquivos de qualquer tipo. O idioma do arquivo gerado não está relacionado ao idioma no qual o código do modelo de texto está escrito.

<#@include file="SharedTemplateCode.txt"#>
<#@ output extension=".cs" #>
namespace Test
{
<#
      foreach (IClass c in ModelStore.AllInstances<IClass>())
      {
#>
   public partial class <#=c.Name#>
   {   }
<#
      }
#>
}

Como usar a geração de texto

O verdadeiro poder de modelagem é obtido quando você usa modelos para projetar o nível de requisitos ou arquitetura. Você pode usar os modelos de texto para fazer parte do trabalho de conversão de idéias de alto nível em código. Em muitos casos, isso não resultar em uma correspondência entre os elementos de modelos UML e classes ou outras partes do código do programa.

Além disso, a transformação depende de seu domínio problemático; Não há nenhum mapeamento universal entre modelos e código.

Aqui estão alguns exemplos de geração de código de modelos:

  • Linhas de produtos. A Fabrikam, Inc. cria e instala os sistemas de manuseio de bagagem de aeroporto. Grande parte do software é muito semelhante entre uma instalação e a próxima, mas a configuração de software depende de qual máquinas de tratamento de bolsa está instalada, e como essas partes são interconectados por belts da transportadora. No início de um contrato, os analistas da Fabrikam abordam os requisitos de gerenciamento de aeroporto e capturar o plano de hardware usando um diagrama de atividade UML. Com esse modelo, a equipe de desenvolvimento gera arquivos de configuração, o código de programa, planos e documentos do usuário. Eles concluem o trabalho manuais adições e ajustes no código. Ganhando experiência a partir de um trabalho para o próximo, eles estendem o escopo do material gerado.

  • Padrões. Muitas vezes, os desenvolvedores na Contoso, Ltd criar sites e projetar o esquema de navegação usando diagramas de classe UML. Cada página da Web é representada por uma classe e associações representam os links de navegação. Os desenvolvedores geram muito do código de um site do modelo. Cada página da Web corresponde a várias classes e as entradas do arquivo de recurso. Este método tem os benefícios que a construção de cada página está de acordo com um padrão único, tornando mais confiável e flexível do que o código escritas à mão. O padrão é nos modelos de geração, enquanto o modelo é usado para capturar os aspectos de variáveis.

  • Esquemas. A Humongous Insurance tem milhares de sistemas em todo o mundo. Esses sistemas usam bancos de dados diferentes, linguagens e interfaces. Internamente, a equipe de arquitetura central publica modelos de processos e conceitos de negócios. Entre esses modelos, equipes locais geram partes de seus esquemas de banco de dados e o intercâmbio, declarações de código de programa e assim por diante. A apresentação gráfica dos modelos ajuda as equipes a discutir propostas. As equipes de criar vários diagramas que mostram a subconjuntos do modelo que se aplicam a diferentes áreas de negócios. Eles também pode usar cores para realçar áreas sujeitas a alterações.

Técnicas importantes para gerar os artefatos

Nos exemplos anteriores, modelos são usados para fins de negócios dependentes diversificados e a interpretação de elementos como, por exemplo, classes e atividades de modelagem varia de um aplicativo para outro. As técnicas a seguir são úteis quando você gerar os artefatos de modelos.

  • Perfis de. Mesmo dentro de área de negócios, a interpretação de um tipo de elemento pode variar. Por exemplo, em um diagrama de site da Web, algumas classes podem representar a páginas da Web e outros representam blocos de conteúdo. Para facilitar para os usuários registrar essas distinções, definem os estereótipos. Estereótipos tornam possível anexar as propriedades adicionais que se aplicam aos elementos desse tipo. Estereótipos são empacotados dentro de perfis. Para obter mais informações, consulte Como: Definir um perfil de estender o UML.

    No código do modelo, é fácil acessar os estereótipos que são definidos em um objeto. Por exemplo:

    public bool HasStereotype(IClass c, string profile, string stereo)
    { return c.AppliedStereotypes.Any
       (s => s.Profile == profile && s.Name == stereo ); }
    
  • Restrita a modelos de. Nem todos os modelos que você pode criar são válidos para cada finalidade. Por exemplo, em modelos de bagagem do aeroporto da Fabrikam, seria incorreto para ter uma mesa de check-in sem uma transportadora de saída. Você pode definir as funções de validação para ajudam os usuários a observar essas restrições. Para obter mais informações, consulte Como: Definir restrições de validação dos modelos UML.

  • Preservar as alterações manuais. Apenas alguns dos arquivos de solução podem ser gerados a partir de um modelo. Na maioria dos casos, você precisa ser capaz de adicionar ou ajustar o conteúdo gerado manualmente. No entanto, é importante que essas alterações manuais devem ser preservadas quando a transformação do modelo é executada novamente.

    Onde seus modelos geram código em .NET idiomas, eles devem gerar classes parciais, de modo que os desenvolvedores podem adicionar métodos e código. Também é útil gerar a cada classe como um par: uma classe base abstrata que contém os métodos e uma classe que contém somente o construtor. Isso permite que os desenvolvedores a substituir os métodos. Para permitir a inicialização a ser substituído, ele é feito em um método separado, em vez de em construtores.

    Onde um modelo gera o XML e outros tipos de saída, pode ser mais difícil manter o conteúdo do manual separados do conteúdo gerado. Um método é criar uma tarefa no processo de compilação que combina dois arquivos. Outro método é para os desenvolvedores ajustar uma cópia local de gerar o modelo.

  • Mova o código em assemblies separados. Não recomendamos a escrever grandes corpos de código nos modelos. É preferível manter o conteúdo gerado separado de computação e modelos de texto também não são suportados para edição de código.

    Em vez disso, se você tiver que realizar cálculos substanciais para gerar o texto, criar essas funções em um assembly separado e chamar seus métodos do modelo.