Geração de texto de tempo de execução com modelos de texto T4
Você pode gerar cadeias de caracteres de texto em seu aplicativo em tempo de execução usando Visual Studio modelos de texto de tempo de execução.O computador onde o aplicativo é executado não tem ter Visual Studio.Modelos de tempo de execução são chamados "modelos de texto pré-processado" porque o tempo de compilação, o modelo gera código que é executado em tempo de execução.
Cada modelo é uma mistura de texto como ela aparecerá na seqüência de caracteres gerada e fragmentos de código de programa.Os fragmentos de programa fornecem valores para as variáveis partes da seqüência de caracteres e também controlam partes condicionais e repetidas.
Por exemplo, o modelo a seguir poderia ser usado em um aplicativo que cria um relatório HTML.
<#@ template language="C#" #>
<html><body>
<h1>Sales for Previous Month</h2>
<table>
<# for (int i = 1; i <= 10; i++)
{ #>
<tr><td>Test name <#= i #> </td>
<td>Test value <#= i * i #> </td> </tr>
<# } #>
</table>
This report is Company Confidential.
</body></html>
Observe que o modelo é uma página HTML na qual as partes variáveis foram substituídas por código de programa.O design de uma página dessas poderia começar escrevendo um protótipo estático da página HTML.Em seguida, você poderia substituir a tabela e outras partes variáveis com código de programa que gera o conteúdo varia de uma vez para o próximo.
Usando um modelo em seu aplicativo faz é mais fácil ver o formulário final da saída do que seria possível em, por exemplo, uma longa série de instruções de gravação.Fazer alterações para o formulário de saída é mais fácil e confiável.
Criando um modelo de texto de tempo de execução em qualquer aplicativo
Para criar um modelo de texto de tempo de execução
No Solution Explorer, no menu de atalho do projeto, escolha Add, Novo Item.
No Adicionar Novo Item caixa de diálogo, selecione Modelo de texto de tempo de execução.(Em Visual Basic procure Comum Items\General.)
Digite um nome para seu arquivo de modelo.
Observação O nome do arquivo de modelo será usado como um nome de classe no código gerado.Portanto, não devem ter espaços ou pontuação.
Escolha Adicionar.
É criado um novo arquivo com extensão .tt.Sua Ferramenta personalizada está definida como TextTemplatingFilePreprocessor.Ele contém as seguintes linhas:
<#@ template language="C#" #> <#@ assembly name="System.Core" #> <#@ import namespace="System.Linq" #> <#@ import namespace="System.Text" #> <#@ import namespace="System.Collections.Generic" #>
Convertendo um arquivo existente em um modelo de tempo de execução
É uma boa maneira de criar um modelo converter um exemplo existente de saída.Por exemplo, se seu aplicativo irá gerar arquivos HTML, você pode iniciar criando um arquivo HTML simples.Verifique se ele funciona corretamente e que sua aparência está correta.Incluí-lo em seu Visual Studio de projeto e convertê-lo em um modelo.
Para converter um arquivo de texto existente em um modelo de tempo de execução
Incluir o arquivo no seu Visual Studio projeto.No Solution Explorer, no menu de atalho do projeto, escolha Add, Item existente.
Definir o arquivo Ferramentas personalizadas propriedade TextTemplatingFilePreprocessor.No Solution Explorer, no menu de atalho do arquivo, escolha Propriedades.
Observação Se a propriedade já está definida, certifique-se de que ele é TextTemplatingFilePreprocessor e não TextTemplatingFileGenerator.Isso pode acontecer se você incluir um arquivo que já possui a extensão .tt.
Altere a extensão de nome de arquivo para .tt.Embora esta etapa é opcional, ajuda evitar abrir o arquivo em um editor incorreto.
Remova quaisquer espaços ou pontuação da principal parte do nome do arquivo.Por exemplo, "My Web Page.tt" seria incorreto, mas "MyWebPage.tt" está correta.O nome do arquivo será usado como um nome de classe no código gerado.
Insira a seguinte linha no início do arquivo.Se você estiver trabalhando em um projeto Visual Basic, substitua "C#" com "VB".
<#@ template language="C#" #>
O conteúdo do modelo de tempo de execução
Diretiva de modelo
Mantenha a primeira linha do modelo como ele era quando você criou o arquivo:
<#@ template language="C#" #>
O parâmetro de idioma dependem do idioma do seu projeto.
Conteúdo simples
Editar o .tt arquivo contém o texto que você deseja que seu aplicativo para gerar.Por exemplo:
<html><body>
<h1>Sales for January</h2>
<!-- table to be inserted here -->
This report is Company Confidential.
</body></html>
Código de programa incorporado
Você pode inserir o código de programa entre <# e #>.Por exemplo:
<table>
<# for (int i = 1; i <= 10; i++)
{ #>
<tr><td>Test name <#= i #> </td>
<td>Test value <#= i * i #> </td> </tr>
<# } #>
</table>
<table>
<#
For i As Integer = 1 To 10
#>
<tr><td>Test name <#= i #> </td>
<td>Test value <#= i*i #> </td></tr>
<#
Next
#>
</table>
Observe que instruções são inseridas entre <# ... #> e expressões são inseridas entre <#= ... #>.Para mais informações, consulte Escrever um modelo de texto T4.
Usando o modelo
O código incorporado do modelo
Sempre que você salva o .tt de arquivo, uma subsidiária de .cs ou .vb arquivo será gerado.Para ver esse arquivo no Solution Explorer, expanda o .tt nó do arquivo.Em um projeto de Visual Basic, você poderá expandir o nó após você clicar em Mostrar todos os arquivos na barra de ferramentas Solution Explorer.
Observe que este arquivo subsidiária contém uma classe parcial que contém um método chamado TransformText().Você pode chamar esse método de seu aplicativo.
Gerando o texto em tempo de execução
No código do aplicativo, você pode gerar o conteúdo do modelo usando uma chamada como esta:
MyWebPage page = new MyWebPage();
String pageContent = page.TransformText();
System.IO.File.WriteAllText("outputPage.html", pageContent);
Dim page = New My.Templates.MyWebPage
Dim pageContent = page.TransformText()
System.IO.File.WriteAllText("outputPage.html", pageContent)
Para colocar a classe gerada em um namespace específico, defina a Custom Tool Namespace propriedade do arquivo de modelo de texto.
Modelos de texto de tempo de execução de depuração
Depurar e testar modelos de texto de tempo de execução da mesma forma como o código comum.
Você pode definir um ponto de interrupção em um modelo de texto.Se você iniciar o aplicativo no modo de depuração de Visual Studio, você pode percorrer o código e avaliar expressões de inspeção da maneira usual.
Passando parâmetros no construtor
Normalmente um modelo deve importar alguns dados de outras partes do aplicativo.Para tornar fácil, o código criado pelo modelo é uma classe parcial.Você pode criar outra parte da mesma classe em outro arquivo no seu projeto.Esse arquivo pode incluir um construtor com parâmetros, propriedades e funções que podem acessadas pelo código incorporado no modelo e pelo resto do aplicativo.
Por exemplo, você pode criar um arquivo separado MyWebPageCode.cs:
partial class MyWebPage
{
private MyData m_data;
public MyWebPage(MyData data) { this.m_data = data; }}
No seu arquivo de modelo MyWebPage.tt, você poderia escrever:
<h2>Sales figures</h2>
<table>
<# foreach (MyDataItem item in m_data.Items)
// m_data is declared in MyWebPageCode.cs
{ #>
<tr><td> <#= item.Name #> </td>
<td> <#= item.Value #> </td></tr>
<# } // end of foreach
#>
</table>
Para usar esse modelo no aplicativo:
MyData data = ...;
MyWebPage page = new MyWebPage(data);
String pageContent = page.TransformText();
System.IO.File.WriteAllText("outputPage.html", pageContent);
Parâmetros do construtor no Visual Basic
Em Visual Basic, o arquivo separado MyWebPageCode.vb contém:
Namespace My.Templates
Partial Public Class MyWebPage
Private m_data As MyData
Public Sub New(ByVal data As MyData)
m_data = data
End Sub
End Class
End Namespace
O arquivo de modelo pode conter:
<#@ template language="VB" #>
<html><body>
<h1>Sales for January</h2>
<table>
<#
For Each item In m_data.Items
#>
<tr><td>Test name <#= item.Name #> </td>
<td>Test value <#= item.Value #> </td></tr>
<#
Next
#>
</table>
This report is Company Confidential.
</body></html>
E o modelo seria chamado, passando o parâmetro no construtor:
Dim data = New My.Templates.MyData
' Add data values here ....
Dim page = New My.Templates.MyWebPage(data)
Dim pageContent = page.TransformText()
System.IO.File.WriteAllText("outputPage.html", pageContent)
Passando dados nas propriedades do modelo
É um método alternativo de passar dados para o modelo adicionar propriedades públicas para a classe de modelo em uma definição de classe parcial.Seu aplicativo pode definir as propriedades antes de invocar TransformText().
Você também pode adicionar campos à sua classe de modelo em uma definição parcial.Isso permitiria passar dados entre execuções sucessivas do modelo.
Usar classes parciais para código
Muitos desenvolvedores preferem evitar a escrita de grandes corpos de código em modelos.Em vez disso, defina métodos em uma classe parcial que tem o mesmo nome do arquivo de modelo.Chame esses métodos do modelo.Dessa forma, o modelo mostra mais claramente o destino cadeia de saída será a aparência.Discussões sobre a aparência do resultado podem ser separadas da lógica de criação de dados que ele exibe.
Assemblies e referências
Se você deseja que seu código de modelo para fazer referência a um.NET ou outro assembly como System.Xml.dll, você deve adicioná-lo ao seu projeto referências da maneira usual.
Se você deseja importar um namespace da mesma maneira como um using instrução, você pode fazer isso com o import diretiva:
<#@ import namespace="System.Xml" #>
Essas diretivas devem ser colocadas no início do arquivo, imediatamente após o <#@template diretiva.
Conteúdo compartilhado
Se você tiver texto que é compartilhado entre vários modelos, pode colocá-lo em um arquivo separado e incluí-la em cada arquivo no qual deve aparecer:
<#@include file="CommonHeader.txt" #>
Conteúdo incluído pode conter qualquer combinação de código de programa e texto sem formatação e pode conter outros incluem diretivas e outras diretivas.
A diretiva de inclusão pode ser usada em qualquer lugar dentro do texto de um arquivo de modelo ou um arquivo incluído.
Herança entre modelos de texto de tempo de execução
Você pode compartilhar conteúdo entre modelos de tempo de execução, escrevendo um modelo de classe base, que pode ser abstract.Use o inherits parâmetro de <@#template#> diretiva para fazer referência a outra classe de modelo de tempo de execução.
Padrão de herança: fragmentos de métodos de Base
No padrão usado no exemplo a seguir, observe os seguintes pontos:
A classe base SharedFragments define métodos dentro de blocos de recurso de classe <#+ ... #>.
A classe base não contém nenhum texto livre.Em vez disso, todos os seus blocos de texto ocorrerem dentro de métodos de classe de recurso.
A classe derivada chama os métodos definidos na SharedFragments.
O aplicativo chama o TextTransform() método de classe derivada, mas não transforma a classe base SharedFragments.
As classes derivadas e base são modelos de texto de tempo de execução: isto é, o Ferramenta personalizada está definida como TextTemplatingFilePreprocessor.
SharedFragments.tt:
<#@ template language="C#" #>
<#+
protected void SharedText(int n)
{
#>
Shared Text <#= n #>
<#+
}
// Insert more methods here if required.
#>
MyTextTemplate1.tt:
<#@ template language="C#" inherits="SharedFragments" #>
begin 1
<# SharedText(2); #>
end 1
MyProgram.cs:
...
MyTextTemplate1 t1 = new MyTextTemplate1();
string result = t1.TransformText();
Console.WriteLine(result);
A saída resultante:
begin 1
Shared Text 2
end 1
Padrão de herança: Texto no corpo da Base
Essa abordagem alternativa para usando herança do modelo, a maior parte do texto é definida no modelo de base.Os modelos derivados fornecem dados e fragmentos de texto que se encaixam em conteúdo base.
AbstractBaseTemplate1.tt:
<#@ template language="C#" #>
Here is the description for this derived template:
<#= this.Description #>
Here is the fragment specific to this derived template:
<#
this.PushIndent(" ");
SpecificFragment(42);
this.PopIndent();
#>
End of common template.
<#+
// State set by derived class before calling TextTransform:
protected string Description = "";
// 'abstract' method to be defined in derived classes:
protected virtual void SpecificFragment(int n) { }
#>
DerivedTemplate1.tt:
<#@ template language="C#" inherits="AbstractBaseTemplate1" #>
<#
// Set the base template properties:
base.Description = "Description for this derived class";
// Run the base template:
base.TransformText();
#>
End material for DerivedTemplate1.
<#+
// Provide a fragment specific to this derived template:
protected override void SpecificFragment(int n)
{
#>
Specific to DerivedTemplate1 : <#= n #>
<#+
}
#>
Código do aplicativo:
...
DerivedTemplate1 t1 = new DerivedTemplate1();
string result = t1.TransformText();
Console.WriteLine(result);
Saída resultante:
Here is the description for this derived template:
Description for this derived class
Here is the fragment specific to this derived template:
Specific to DerivedTemplate1 : 42
End of common template.
End material for DerivedTemplate1.
Tópicos relacionados
Modelos de tempo de design: Se você quiser usar um modelo para gerar código que passa a fazer parte do seu aplicativo, consulte Geração de código de tempo de design usando modelos de texto T4.
Modelos de tempo de execução podem ser usados em qualquer aplicativo onde os modelos e seu conteúdo são determinadas em tempo de compilação.Mas se você quiser escrever um Visual Studio extensão gera texto modelos que alterar em tempo de execução, consulte Invocar a transformação de texto em uma extensão do VS.
Consulte também
Conceitos
Modelos de texto T4 e de geração de código
Escrever um modelo de texto T4
Outros recursos
Noções básicas sobre T4: Pré-processado modelos de texto por Oleg Sych