Sdílet prostřednictvím


Návod: Vytvoření kódu pomocí textových šablon

Generování kódu umožňuje vytvářet kód programu, který silný a ještě lze snadno změnit při změně zdrojového modelu.Tento kontrast s alternativní techniky psaní zcela obecného programu, který přijímá konfigurační soubor, který je pružnější, ale výsledky v kódu, který je ani tak snadno číst a měnit, ani takové dobrý výkon.Názorný tuto výhodu.

Zadaný kód XML pro čtení

Obor názvů System.Xml poskytuje komplexní nástroje pro načítání dokumentu XML a potom jej volně navigaci v paměti.Bohužel všechny uzly mají stejného typu XmlNode.Proto je velmi snadné programování udělají například očekává nesprávný typ podřízený uzel nebo chybné atributy.

V tomto příkladu projektu šablony přečte soubor XML a generuje tříd, které odpovídají každý typ uzlu.V kódu rukou můžete tyto třídy vyhledejte soubor XML.Můžete také spustit aplikaci na všechny soubory, které používají stejné typy uzlů.Účelem ukázkový soubor XML je poskytnout všechny typy uzel požadované aplikace řešit.

[!POZNÁMKA]

Aplikace xsd.exe, který je součástí Visual Studio, můžete generovat silnými tříd ze souborů XML.Šablony zde slouží jako příklad.

Zde je ukázkový soubor:

<?xml version="1.0" encoding="utf-8" ?>
<catalog>
  <artist id ="Mike%20Nash" name="Mike Nash Quartet">
    <song id ="MikeNashJazzBeforeTeatime">Jazz Before Teatime</song>
    <song id ="MikeNashJazzAfterBreakfast">Jazz After Breakfast</song>
  </artist>
  <artist id ="Euan%20Garden" name="Euan Garden">
    <song id ="GardenScottishCountry">Scottish Country Garden</song>
  </artist>
</catalog>

V projektu konstrukce tohoto postupu, můžete zapsat kód například následující a technologie IntelliSense vyzve správné názvy atributů a podřízené při psaní:

Catalog catalog = new Catalog(xmlDocument);
foreach (Artist artist in catalog.Artist)
{
  Console.WriteLine(artist.name);
  foreach (Song song in artist.Song)
  {
    Console.WriteLine("   " + song.Text);
  }
}

Tento kontrast s netypovou kód, který může psát bez šablony:

XmlNode catalog = xmlDocument.SelectSingleNode("catalog");
foreach (XmlNode artist in catalog.SelectNodes("artist"))
{
    Console.WriteLine(artist.Attributes["name"].Value);
    foreach (XmlNode song in artist.SelectNodes("song"))
    {
         Console.WriteLine("   " + song.InnerText);
     }
}

Silnými verze nebudou změny schématu XML změny tříd.Kompilátor bude zvýraznění částí kódu aplikace, který musí být změněno.Netypovou verzi, která používá obecný kód XML je bez takové podpory.

V tomto projektu jeden soubor šablony lze generovat třídy, které je možné vytvořit zadanou verzi.

Nastavení projektu

Vytvoření nebo otevření projektu C#

Tuto techniku můžete použít libovolný kód projektu.Tento návod používá projekt C# a pro účely testování používáme aplikace konzoly.

Jak vytvořit nový projekt

  1. Na soubor nabídce klepněte na příkaz Nový a klepněte na tlačítko projektu.

  2. Klepněte Visual C# uzlu a poté v šablony podokně klepněte na tlačítko aplikace konzoly.

Do projektu přidat soubor XML prototypu

Účelem tohoto souboru je poskytnout vzorky typy uzlů XML, které chcete číst aplikace.Mohl být soubor, který bude použit pro testování aplikace.Šablona ohlásí třídy C# pro každý typ uzlu v tomto souboru.

Soubor by měla být součástí projektu, aby šablony můžete číst, ale není integrována do zkompilované aplikace.

Přidání souboru XML

  1. V Aplikaci Solution Explorer, klepněte pravým tlačítkem myši projekt, klepněte na tlačítko Přidat a klepněte na tlačítko Nové položky.

  2. V Přidat novou položku vyberte položku Soubor XML z šablony podokně.

  3. Přidáte vzorek obsahu do souboru.

  4. Tento návod název souboru exampleXml.xml.Nastavte obsah souboru XML v předchozí části.

..

Přidání souboru testovací kód

Přidat soubor C# do projektu a zapisovat do něj ukázkový kód, který chcete zapsat.Příklad:

using System;
namespace MyProject
{
  class CodeGeneratorTest
  {
    public void TestMethod()
    {
      Catalog catalog = new Catalog(@"..\..\exampleXml.xml");
      foreach (Artist artist in catalog.Artist)
      {
        Console.WriteLine(artist.name);
        foreach (Song song in artist.Song)
        {
          Console.WriteLine("   " + song.Text);
} } } } }

V této fázi tento kód nelze kompilovat.Psaní šablona bude generovat tříd, které umožňují úspěšné.

Výstup této funkce test proti známým obsah souboru XML, například zkontrolovat více komplexní test.Ale v tomto návodu budeme spokojeni při kompilaci zkušební metody.

Přidání textového souboru šablony

Přidání textového souboru šablony a nastavení výstupní rozšíření na ".cs".

Přidání textového souboru šablony do projektu

  1. V Aplikaci Solution Explorer, klepněte pravým tlačítkem myši projekt, klepněte na tlačítko Přidata klepněte na tlačítko Nové položky.

  2. V Přidat novou položku dialogovém okně vyberte Text šablony z šablony podokně.

    [!POZNÁMKA]

    Zkontrolujte, zda přidat Text šablony a není předzpracovány Text šablony.

  3. V souboru šablony směrnice změnit hostspecific k atributu true.

    Tato změna umožní kód šablony k získání přístupu k Visual Studio služeb.

  4. Směrnice výstup změňte atribut rozšíření na ".cs" Šablona generuje soubor C#.V projektu aplikace Visual Basic by jej změnit na "VB".

  5. Uložte soubor.V této fázi by měl obsahovat soubor šablony text tyto řádky:

    <#@ template debug="false" hostspecific="true" language="C#" #>
    <#@ output extension=".cs" #>
    

.

Všimněte si, že .cs soubor, zobrazí se v aplikaci Solution Explorer jako dceřiný soubor šablony.Můžete je zobrazit klepnutím na tlačítko [+] vedle názvu souboru šablony.Tento soubor je generováno z šablony souboru při každém uložení nebo přesunutí fokusu mimo soubor šablony.Generovaný soubor bude zpracován jako část projektu.

Pohodlí při vývoji souboru šablony, uspořádejte okna soubor šablony a generovaného souboru tak, že uvidíte vedle sebe.To umožňuje okamžitě zobrazit výstup šablony.Také zjistíte, že když Šablona generuje neplatný kód C#, chyby se zobrazí v okně chybové zprávy.

Veškeré úpravy provádět přímo v souboru generovaného budou ztraceny při každém uložení souboru šablony.Si proto vyhnout úpravy generovaného souboru, nebo upravit pouze pro krátký experimenty.Někdy je užitečné zkuste krátké fragment kódu generovaného souboru, kde technologie IntelliSense je v provozu, a zkopírujte jej do souboru šablony.

Vývoj Text šablony

Po nejlepší agilní rozvoj poradenství jsme bude rozvíjet šablony v malých krocích zrušením některé chyby v každém přírůstku, dokud testovací kód zkompiluje a spustí správně.

Vzorový kód generován

Testovací kód vyžaduje třídu pro každý uzel v souboru.Proto některé chyby kompilace bude zmizí připojit tyto řádky šablony a potom uložit:

  class Catalog {} 
  class Artist {}
  class Song {}

Pomůže vám zjistit, co je potřeba, ale prohlášení by generované z typů uzlů v ukázkovém souboru XML.Odstraníte tyto řádky experimentální ze šablony.

Generovat kód aplikace ze souboru XML modelu

Čtení souboru XML a generovat deklarace tříd, nahradíte šablonu s následující kód šablony obsahu:

<#@ template debug="false" hostspecific="true" language="C#" #>
<#@ output extension=".cs" #>
<#@ assembly name="System.Xml"#>
<#@ import namespace="System.Xml" #>
<#
 XmlDocument doc = new XmlDocument();
 // Replace this file path with yours:
 doc.Load(@"C:\MySolution\MyProject\exampleXml.xml");
 foreach (XmlNode node in doc.SelectNodes("//*"))
 {
#>
  public partial class <#= node.Name #> {}
<#
 }
#>

Cesta k souboru nahraďte správnou cestu k projektu.

Všimněte si oddělovače bloků kódu <#...#>.Tyto oddělovače bracket fragment kódu programu, který generuje text.Oddělovače bloků výraz <#=...#> bracket výraz, který lze vyhodnotit na řetězec.

Při psaní šablonu, která generuje zdrojový kód aplikace se zabývají dva texty samostatný program.Program uvnitř oddělovačů blok kódu spustí pokaždé, když jste šablonu uložit nebo fokus přesunout do jiného okna.Text, který generuje, který se zobrazí mimo oddělovače, je zkopírován do generovaného souboru a stane se součástí kód aplikace.

<#@assembly#> Směrnice se chová jako odkaz zpřístupnění sestavení kód šablony.V seznamu zobrazit šablony sestav je seznamu odkazy v aplikaci project.

<#@import#> Směrnice pracuje stejně jako using prohlášení, budete moci použít krátké názvy tříd v importované oboru názvů.

Bohužel, ačkoli tato šablona generuje kód, vytváří deklaraci třídy pro každý uzel v příklad souboru XML, tak, že pokud existuje několik instancí <song> uzlu, zobrazí se několik prohlášení třídy song.

Přečtěte si soubor modelu a potom generovat kód

Mnoho šablon text podle vzorku, v němž první část šablony přečte zdrojový soubor a generuje druhé části šablony.Musíme číst všechny typy uzlů, které obsahuje shrnutí příklad souboru a pak vygenerovat deklarace třídy.Jiné <#@import#> je potřeba, takže můžeme použítDictionary<>:

<#@ template debug="false" hostspecific="true" language="C#" #>
<#@ output extension=".cs" #>
<#@ assembly name="System.Xml"#>
<#@ import namespace="System.Xml" #>
<#@ import namespace="System.Collections.Generic" #>
<#
 // Read the model file
 XmlDocument doc = new XmlDocument();
 doc.Load(@"C:\MySolution\MyProject\exampleXml.xml");
 Dictionary <string, string> nodeTypes = 
        new Dictionary<string, string>();
 foreach (XmlNode node in doc.SelectNodes("//*"))
 {
   nodeTypes[node.Name] = "";
 }
 // Generate the code
 foreach (string nodeName in nodeTypes.Keys)
 {
#>
  public partial class <#= nodeName #> {}
<#
 }
#>

Přidání pomocné metody

Blok ovládací funkce třídy je blok, ve kterém můžete definovat pomocné metody.Blok je vymezen <#+...#> a musí být uvedeny jako poslední blok v souboru.

Pokud dáváte přednost názvy tříd začínat velkým písmenem, můžete poslední část šablony nahradit kód následující šablony:

// Generate the code
 foreach (string nodeName in nodeTypes.Keys)
 {
#>
  public partial class <#= UpperInitial(nodeName) #> {}
<#
 }
#>
<#+
 private string UpperInitial(string name)
 { return name[0].ToString().ToUpperInvariant() + name.Substring(1); }
#>

V této fázi .cs vygenerovaný soubor obsahuje následující prohlášení:

  public partial class Catalog {}
  public partial class Artist {}
  public partial class Song {}

Další podrobnosti, jako například vlastnosti pro podřízené uzly, atributy a vnitřní text lze přidat pomocí stejný přístup.

Přístup k rozhraní API aplikace Visual Studio

Nastavení hostspecific atribut <#@template#> směrnice umožňuje získat přístup k šabloně Visual Studio rozhraní API.Získání umístění souborů projektu pomocí absolutní cesta v kódu šablony, aby to můžete použít šablony.

<#@ template debug="false" hostspecific="true" language="C#" #>
...
<#@ assembly name="EnvDTE" #>
...
EnvDTE.DTE dte = (EnvDTE.DTE) ((IServiceProvider) this.Host)
                       .GetService(typeof(EnvDTE.DTE));
// Open the prototype document.
XmlDocument doc = new XmlDocument();
doc.Load(System.IO.Path.Combine(dte.ActiveDocument.Path, "exampleXml.xml"));

Vyplnění textu šablony

Následující šablony obsahu generuje kód, který umožňuje sestavit a spustit kód testu.

<#@ template debug="false" hostspecific="true" language="C#" #>
<#@ output extension=".cs" #>
<#@ assembly name="System.Xml" #>
<#@ assembly name="EnvDTE" #>
<#@ import namespace="System.Xml" #>
<#@ import namespace="System.Collections.Generic" #>
using System; 
using System.Collections.Generic; 
using System.Linq; 
using System.Xml; 
namespace MyProject 
{
<#
 // Map node name --> child name --> child node type
 Dictionary<string, Dictionary<string, XmlNodeType>> nodeTypes = new Dictionary<string, Dictionary<string, XmlNodeType>>();

 // The Visual Studio host, to get the local file path.
 EnvDTE.DTE dte = (EnvDTE.DTE) ((IServiceProvider) this.Host)
                       .GetService(typeof(EnvDTE.DTE));
 // Open the prototype document.
 XmlDocument doc = new XmlDocument();
 doc.Load(System.IO.Path.Combine(dte.ActiveDocument.Path, "exampleXml.xml"));
 // Inspect all the nodes in the document.
 // The example might contain many nodes of the same type, 
 // so make a dictionary of node types and their children.
 foreach (XmlNode node in doc.SelectNodes("//*"))
 {
   Dictionary<string, XmlNodeType> subs = null;
   if (!nodeTypes.TryGetValue(node.Name, out subs))
   {
     subs = new Dictionary<string, XmlNodeType>();
     nodeTypes.Add(node.Name, subs);
   }
   foreach (XmlNode child in node.ChildNodes)
   {
     subs[child.Name] = child.NodeType;
   } 
   foreach (XmlNode child in node.Attributes)
   {
     subs[child.Name] = child.NodeType;
   }
 }
 // Generate a class for each node type.
 foreach (string className in nodeTypes.Keys)
 {
    // Capitalize the first character of the name.
#>
    partial class <#= UpperInitial(className) #>
    { 
      private XmlNode thisNode; 
      public <#= UpperInitial(className) #>(XmlNode node)  
      { thisNode = node; }

<#
    // Generate a property for each child.
    foreach (string childName in nodeTypes[className].Keys)
    {
      // Allow for different types of child.
      switch (nodeTypes[className][childName])
      {
         // Child nodes:
         case XmlNodeType.Element:
#>
      public IEnumerable<<#=UpperInitial(childName)#>><#=UpperInitial(childName) #>
      {  
        get  
        {  
           foreach (XmlNode node in 
                thisNode.SelectNodes("<#=childName#>"))  
             yield return new <#=UpperInitial(childName)#>(node);  
      } }
<#
         break;
         // Child attributes:
         case XmlNodeType.Attribute:
#>
      public string <#=childName #>
      { get { return thisNode.Attributes["<#=childName#>"].Value; } }
<#
         break;
         // Plain text:
         case XmlNodeType.Text:
#>
      public string Text  { get { return thisNode.InnerText; } }
<#
         break;
       } // switch
     } // foreach class child
  // End of the generated class:
#>
   } 
<#
 } // foreach class

   // Add a constructor for the root class 
   // that accepts an XML filename.
   string rootClassName = doc.SelectSingleNode("*").Name;
#>
   partial class <#= UpperInitial(rootClassName) #> 
   { 
      public <#= UpperInitial(rootClassName) #>(string fileName)  
      { 
        XmlDocument doc = new XmlDocument(); 
        doc.Load(fileName); 
        thisNode = doc.SelectSingleNode("<#=rootClassName#>"); 
      } 
   } 
}
<#+
   private string UpperInitial(string name)
   {
      return name[0].ToString().ToUpperInvariant() + name.Substring(1);
   }
#>

Spuštění testovacího programu

V hlavní aplikace konzoly provede následující řádky zkušební metody.Stisknutím klávesy F5 spuštění programu v režimu ladění:

using System;
namespace MyProject
{ class Program
  { static void Main(string[] args)
    { new CodeGeneratorTest().TestMethod();
      // Allow user to see the output:
      Console.ReadLine();
} } }

Psaní a aktualizaci aplikace

Aplikace lze zapsat nyní silnými stylu pomocí vygenerované třídy namísto obecného kódu XML.

Při změně schématu XML, lze snadno generovat nové třídy.Kompilátor bude informovat vývojáře, kde musí být aktualizován kód aplikace.

Chcete-li obnovit tříd při změně příklad souboru XML, klepněte na tlačítko Transformace všechny šablony v aplikaci Solution Explorer nástrojů.

Závěr

Tento názorný několik technik a výhody pro generování kódu:

  • Generování kódu je vytvoření části zdrojového kódu aplikace modelu.Model obsahuje informace ve formě vhodné pro aplikační domény a může změnit v průběhu života aplikace.

  • Silné zadání je výhodou generování kódu.Zatímco model představuje informace ve formě, která je vhodnější pro uživatele, generovaný kód umožňuje jiné části aplikace řešit pomocí sady typů informací.

  • Technologie IntelliSense a kompilátoru můžete vytvořit kód, který dodržuje schéma modelu, i když píšete kód nové při aktualizaci schématu.

  • Přídavek jeden zdát soubor šablony projektu může poskytnout tyto dávky.

  • Text šablony můžete vyvinuty a testovány rychle a postupně.

V tomto návodu je kód programu skutečně generována z instancí modelu reprezentativní příklad soubory XML, které bude zpracovávat žádosti.V formálnější přístup schématu XML by vstup do šablony ve formě souboru XSD nebo definice domény specifické pro jazyk.Tento přístup by usnadnit šablony k určení vlastností, jako je násobnost vztah.

Odstraňování textu šablony

Pokud jste viděli transformace nebo sestavování chyby v šabloně Seznam chyb, nebo pokud nebyla správně vytvořena výstupní soubor, text šablony můžete vyřešit pomocí postupů popsaných v Generování souborů pomocí nástroje TextTransform.

Viz také

Koncepty

Vytvoření kódu v době návrhu pomocí textových šablon T4

Tvorba textové šablony T4