Sdílet prostřednictvím


Přístup k modelům z textových šablon

Pomocí textových šablon můžete vytvářet soubory sestav, soubory zdrojového kódu a další textové soubory založené na jazykových modelech specifických pro doménu. Základní informace o textových šablonách najdete v tématu Generování kódu a textové šablony T4. Textové šablony budou fungovat v experimentálním režimu při ladění DSL a budou také fungovat na počítači, na kterém jste nasadili DSL.

Poznámka:

Při vytváření řešení DSL se vygenerují ukázkové textové šablony *.tt soubory v projektu ladění. Když změníte názvy tříd domény, tyto šablony už nebudou fungovat. Nicméně obsahují základní direktivy, které potřebujete, a poskytují příklady, které můžete aktualizovat tak, aby odpovídaly vašemu DSL.

Přístup k modelu z textové šablony:

  • Nastavte zděděnou vlastnost direktivy šablony na Microsoft.VisualStudio.TextTemplating.VSHost.ModelingTextTransformation. Tím získáte přístup ke Storu.

  • Zadejte procesory direktiv pro DSL, ke kterým chcete získat přístup. Tím se načte sestavení pro váš DSL, abyste mohli použít jeho doménové třídy, vlastnosti a relace v kódu textové šablony. Načte také zadaný soubor modelu.

    Soubor .tt podobný následujícímu příkladu se vytvoří v projektu ladění při vytvoření nového řešení sady Visual Studio ze šablony DSL Minimal Language.

<#@ template inherits="Microsoft.VisualStudio.TextTemplating.VSHost.ModelingTextTransformation" #>
<#@ output extension=".txt" #>
<#@ MyLanguage processor="MyLanguageDirectiveProcessor" requires="fileName='Sample.myDsl1'" #>

This text will be output directly.

This is the name of the model: <#= this.ModelRoot.Name #>

Here is a list of elements in the model:
<#
  // When you change the DSL Definition, some of the code below may not work.
  foreach (ExampleElement element in this.ExampleModel.Elements)
  {#>
<#= element.Name #>
<#
  }
#>

Všimněte si následujících bodů o této šabloně:

  • Šablona může používat doménové třídy, vlastnosti a relace, které jste definovali v definici DSL.

  • Šablona načte soubor modelu, který zadáte ve requires vlastnosti.

  • Vlastnost obsahuje this kořenový prvek. Odtud může váš kód přejít na další prvky modelu. Název vlastnosti je obvykle stejný jako kořenová třída domény vašeho DSL. V tomto příkladu je to this.ExampleModel.

  • I když jazyk, ve kterém jsou fragmenty kódu napsané, je C#, můžete generovat text libovolného druhu. Kód v jazyce Visual Basic můžete také napsat přidáním vlastnosti language="VB" do direktivy template .

  • Pokud chcete šablonu ladit, přidejte debug="true" ji do direktivy template . Pokud dojde k výjimce, šablona se otevře v jiné instanci sady Visual Studio. Pokud chcete rozdělit ladicí program v určitém bodě kódu, vložte příkaz. System.Diagnostics.Debugger.Break();

    Další informace naleznete v tématu Ladění textové šablony T4.

O procesoru direktiv DSL

Šablona může používat doménové třídy, které jste definovali v definici DSL. To se týká direktivy, která se obvykle zobrazuje blízko začátku šablony. V předchozím příkladu je to následující.

<#@ MyLanguage processor="MyLanguageDirectiveProcessor" requires="fileName='Sample.myDsl1'" #>

Název direktivy ( MyLanguagev tomto příkladu) je odvozen od názvu vašeho DSL. Vyvolá procesor direktiv, který je generován jako součást vašeho DSL. Zdrojový kód najdete v dsl\GeneratedCode\DirectiveProcessor.cs.

Procesor direktiv DSL provádí dvě hlavní úlohy:

  • Efektivně vloží direktivy sestavení a importu do šablony, která odkazuje na vaši DSL. To vám umožní používat třídy domény v kódu šablony.

  • Načte soubor, který zadáte v parametru requires , a nastaví vlastnost this , která odkazuje na kořenový prvek načteného modelu.

Ověření modelu před spuštěním šablony

Model můžete před spuštěním šablony ověřit.

<#@ MyLanguage processor="MyLanguageDirectiveProcessor" requires="fileName='Sample.myDsl1';validation='open|load|save|menu'" #>

Všimněte si, že:

  1. Parametry filename jsou validation oddělené textem ";" a nesmí existovat žádné jiné oddělovače ani mezery.

  2. Seznam kategorií ověření určuje, které metody ověřování se budou spouštět. Více kategorií by mělo být odděleno znakem | a nesmí existovat žádné jiné oddělovače ani mezery.

    Pokud dojde k chybě, zobrazí se v okně chyb a výsledný soubor bude obsahovat chybovou zprávu.

Přístup k více modelům z textové šablony

Poznámka:

Tato metoda umožňuje číst více modelů ve stejné šabloně, ale nepodporuje odkazy ModelBus. Pokud chcete číst modely, které jsou propojené pomocí odkazů ModelBus, přečtěte si téma Použití sady Visual Studio ModelBus v textové šabloně.

Pokud chcete získat přístup k více než jednomu modelu ze stejné textové šablony, musíte pro každý model volat vygenerovaný procesor direktiv jednou. V parametru requires musíte zadat název souboru každého modelu. V parametru provides musíte zadat názvy, které chcete použít pro kořenovou třídu domény. V každém volání direktivy je nutné zadat různé hodnoty provides parametrů. Předpokládejme například, že máte tři soubory modelu s názvem Library.xyz, School.xyz a Work.xyz. Abyste k nim měli přístup ze stejné textové šablony, musíte napsat tři volání direktiv, která se podobají následujícím voláním.

<#@ ExampleModel processor="<YourLanguageName>DirectiveProcessor" requires="fileName='Library.xyz'" provides="ExampleModel=LibraryModel" #>
<#@ ExampleModel processor="<YourLanguageName>DirectiveProcessor" requires="fileName='School.xyz'" provides="ExampleModel=SchoolModel" #>
<#@ ExampleModel processor="<YourLanguageName>DirectiveProcessor" requires="fileName='Work.xyz'" provides="ExampleModel=WorkModel" #>

Poznámka:

Tento ukázkový kód je určený pro jazyk, který je založený na šabloně řešení Minimální jazyk.

Pro přístup k modelům v textové šabloně teď můžete napsat kód podobný kódu v následujícím příkladu.

<#
foreach (ExampleElement element in this.LibraryModel.Elements)
...
foreach (ExampleElement element in this.SchoolModel.Elements)
...
foreach (ExampleElement element in this.WorkModel.Elements)
...
#>

Dynamické načítání modelů

Pokud chcete určit za běhu, které modely se mají načíst, můžete soubor modelu dynamicky načíst do kódu programu namísto použití direktivy specifické pro DSL.

Jednou z funkcí direktivy specifické pro DSL je však import oboru názvů DSL, aby kód šablony mohl používat třídy domény definované v této DSL. Vzhledem k tomu, že direktivu nepoužíváte, musíte přidat <direktivy sestavení> a <importu> pro všechny modely, které byste mohli načíst. To je snadné, pokud různé modely, které byste mohli načíst, jsou všechny instance stejné DSL.

K načtení souboru je nejúčinnější metoda pomocí sady Visual Studio ModelBus. V typickém scénáři použije vaše textová šablona direktivu specifickou pro DSL k načtení prvního modelu obvyklým způsobem. Tento model by obsahoval odkazy ModeluBus na jiný model. ModelBus můžete použít k otevření odkazovaného modelu a přístupu k určitému prvku. Další informace naleznete v tématu Použití sady Visual Studio ModelBus v textové šabloně.

V méně obvyklém scénáři můžete chtít otevřít soubor modelu, pro který máte pouze název souboru a který nemusí být v aktuálním projektu sady Visual Studio. V tomto případě můžete soubor otevřít pomocí techniky popsané v tématu Postupy: Otevření modelu ze souboru v kódu programu.

Generování více souborů ze šablony

Pokud chcete vygenerovat několik souborů – například pro každý prvek modelu vygenerovat samostatný soubor, existuje několik možných přístupů. Ve výchozím nastavení se z každého souboru šablony vytvoří jenom jeden soubor.

Rozdělení dlouhého souboru

V této metodě použijete šablonu k vygenerování jednoho souboru odděleného oddělovačem. Potom soubor rozdělíte do jeho částí. Existují dvě šablony, jedna pro vygenerování jednoho souboru a druhá k jeho rozdělení.

LoopTemplate.t4 vygeneruje dlouhý jeden soubor. Všimněte si, že jeho přípona souboru je .t4, protože by neměla být zpracována přímo po kliknutí na transformovat všechny šablony. Tato šablona přebírá parametr, který určuje řetězec oddělovače, který odděluje segmenty:

<#@ template inherits="Microsoft.VisualStudio.TextTemplating.VSHost.ModelingTextTransformation" #>
<#@ parameter name="delimiter" type="System.String" #>
<#@ output extension=".txt" #>
<#@ MyDSL processor="MyDSLDirectiveProcessor" requires="fileName='SampleModel.mydsl1';validation='open|load|save|menu'" #>
<#
  // Create a file segment for each element:
  foreach (ExampleElement element in this.ExampleModel.Elements)
  {
    // First item is the delimiter:
#>
<#= string.Format(delimiter, element.Id) #>

   Element: <#= element.Name #>
<#
   // Here you generate more content derived from the element.
  }
#>

LoopSplitter.ttLoopTemplate.t4vyvolá a potom rozdělí výsledný soubor do jeho segmentů. Všimněte si, že tato šablona nemusí být šablonou modelování, protože nečte model.

<#@ template hostspecific="true" language="C#" #>
<#@ output extension=".txt" #>
<#@ import namespace="Microsoft.VisualStudio.TextTemplating" #>
<#@ import namespace="System.Runtime.Remoting.Messaging" #>
<#@ import namespace="System.IO" #>

<#
  // Get the local path:
  string itemTemplatePath = this.Host.ResolvePath("LoopTemplate.t4");
  string dir = Path.GetDirectoryName(itemTemplatePath);

  // Get the template for generating each file:
  string loopTemplate = File.ReadAllText(itemTemplatePath);

  Engine engine = new Engine();

  // Pass parameter to new template:
  string delimiterGuid = Guid.NewGuid().ToString();
  string delimiter = "::::" + delimiterGuid + ":::";
  CallContext.LogicalSetData("delimiter", delimiter + "{0}:::");
  string joinedFiles = engine.ProcessTemplate(loopTemplate, this.Host);

  string [] separateFiles = joinedFiles.Split(new string [] {delimiter}, StringSplitOptions.None);

  foreach (string nameAndFile in separateFiles)
  {
     if (string.IsNullOrWhiteSpace(nameAndFile)) continue;
     string[] parts = nameAndFile.Split(new string[]{":::"}, 2, StringSplitOptions.None);
     if (parts.Length < 2) continue;
#>
 Generate: [<#= dir #>] [<#= parts[0] #>]
<#
     // Generate a file from this item:
     File.WriteAllText(Path.Combine(dir, parts[0] + ".txt"), parts[1]);
  }
#>