<#...#> 可以包含语句
<#=...#> 用于表达式,提供“输出”操作
<#+ ...> 使用类功能控制块向文本模板添加方法、属性、字段,必须作为文件中最后一个块显示
assembly 指令使指定的程序集可供模板代码使用,方式与 Visual Studio 项目中的“引用”部分相同。 您无需包括对 System.dll 的引用,它是自动引用的。 import 指令允许您使用类型而不使用其完全限定名,方式与普通程序文件中的 using 指令相同
若要从相对于文本模板的位置加载文件,可以使用 this.Host.ResolvePath()。 若要使用 this.Host,您必须在 template 中设置 hostspecific="true",还可以使用 this.Host.TemplateFile,它标识当前模板文件的名称。
如果已安装 Visual Studio 可视化和建模 SDK,则可以在每次执行生成时自动转换所有模板。 为此,可在文本编辑器中编辑项目文件(.csproj 或 .vbproj),然后在文件末尾附近(其他任何<import> 语句之后)添加以下行:
<Import Project="$(MSBuildExtensionsPath)MicrosoftVisualStudiov11.0TextTemplatingMicrosoft.TextTemplating.targets" /> <PropertyGroup> <TransformOnBuild>true</TransformOnBuild> <!-- Other properties can be inserted here --> </PropertyGroup>
若要在 Visual Studio 错误窗口中放置错误消息和警告消息,可以使用以下方法:
<#@ template debug="false" hostspecific="true" language="C#" #> <#Error("An error message");#> <#Warning("A warning message");#>
类功能控制块是一个可以在其中定义辅助方法的块。 该块以 <#+...#> 分隔,并且必须作为文件中的最后一个块显示。
通过设置 <#@template#> 指令的 hostspecific 特性,可以允许模板获取对 Visual Studio API 的访问。 模板可以使用此功能获取项目文件的位置,以避免在模板代码中使用绝对文件路径。
一个读取XML的例子:
1 <?xml version="1.0" encoding="utf-8" ?> 2 <catalog> 3 <artist id ="Mike%20Nash" name="Mike Nash Quartet"> 4 <song id ="MikeNashJazzBeforeTeatime">Jazz Before Teatime</song> 5 <song id ="MikeNashJazzAfterBreakfast">Jazz After Breakfast</song> 6 </artist> 7 <artist id ="Euan%20Garden" name="Euan Garden"> 8 <song id ="GardenScottishCountry">Scottish Country Garden</song> 9 </artist> 10 </catalog>
1 <#@ template debug="false" hostspecific="true" language="C#" #> 2 <#@ output extension=".cs" #> 3 <#@ assembly name="System.Xml" #> 4 <#@ assembly name="EnvDTE" #> 5 <#@ import namespace="System.Xml" #> 6 <#@ import namespace="System.Collections.Generic" #> 7 using System; 8 using System.Collections.Generic; 9 using System.Linq; 10 using System.Xml; 11 namespace MyProject 12 { 13 <# 14 // Map node name --> child name --> child node type 15 Dictionary<string, Dictionary<string, XmlNodeType>> nodeTypes = new Dictionary<string, Dictionary<string, XmlNodeType>>(); 16 17 // The Visual Studio host, to get the local file path. 18 EnvDTE.DTE dte = (EnvDTE.DTE) ((IServiceProvider) this.Host) 19 .GetService(typeof(EnvDTE.DTE)); 20 // Open the prototype document. 21 XmlDocument doc = new XmlDocument(); 22 doc.Load(System.IO.Path.Combine(dte.ActiveDocument.Path, "exampleXml.xml")); 23 // Inspect all the nodes in the document. 24 // The example might contain many nodes of the same type, 25 // so make a dictionary of node types and their children. 26 foreach (XmlNode node in doc.SelectNodes("//*")) 27 { 28 Dictionary<string, XmlNodeType> subs = null; 29 if (!nodeTypes.TryGetValue(node.Name, out subs)) 30 { 31 subs = new Dictionary<string, XmlNodeType>(); 32 nodeTypes.Add(node.Name, subs); 33 } 34 foreach (XmlNode child in node.ChildNodes) 35 { 36 subs[child.Name] = child.NodeType; 37 } 38 foreach (XmlNode child in node.Attributes) 39 { 40 subs[child.Name] = child.NodeType; 41 } 42 } 43 // Generate a class for each node type. 44 foreach (string className in nodeTypes.Keys) 45 { 46 // Capitalize the first character of the name. 47 #> 48 partial class <#= UpperInitial(className) #> 49 { 50 private XmlNode thisNode; 51 public <#= UpperInitial(className) #>(XmlNode node) 52 { thisNode = node; } 53 54 <# 55 // Generate a property for each child. 56 foreach (string childName in nodeTypes[className].Keys) 57 { 58 // Allow for different types of child. 59 switch (nodeTypes[className][childName]) 60 { 61 // Child nodes: 62 case XmlNodeType.Element: 63 #> 64 public IEnumerable<<#=UpperInitial(childName)#>><#=UpperInitial(childName) #> 65 { 66 get 67 { 68 foreach (XmlNode node in 69 thisNode.SelectNodes("<#=childName#>")) 70 yield return new <#=UpperInitial(childName)#>(node); 71 } } 72 <# 73 break; 74 // Child attributes: 75 case XmlNodeType.Attribute: 76 #> 77 public string <#=childName #> 78 { get { return thisNode.Attributes["<#=childName#>"].Value; } } 79 <# 80 break; 81 // Plain text: 82 case XmlNodeType.Text: 83 #> 84 public string Text { get { return thisNode.InnerText; } } 85 <# 86 break; 87 } // switch 88 } // foreach class child 89 // End of the generated class: 90 #> 91 } 92 <# 93 } // foreach class 94 95 // Add a constructor for the root class 96 // that accepts an XML filename. 97 string rootClassName = doc.SelectSingleNode("*").Name; 98 #> 99 partial class <#= UpperInitial(rootClassName) #> 100 { 101 public <#= UpperInitial(rootClassName) #>(string fileName) 102 { 103 XmlDocument doc = new XmlDocument(); 104 doc.Load(fileName); 105 thisNode = doc.SelectSingleNode("<#=rootClassName#>"); 106 } 107 } 108 } 109 <#+ 110 private string UpperInitial(string name) 111 { 112 return name[0].ToString().ToUpperInvariant() + name.Substring(1); 113 } 114 #>