演练:将主机连接至生成的指令处理器
可以编写拥有处理文本模板的宿主。 基本的自定义宿主在 演练:创建自定义文本模板宿主将演示。 可以扩展承载添加功能 (如生成多个输出的文件。
在本演练中,将展开自定义宿主,以便支持调用指令处理器的文本模板。 在定义域特定语言 (dsl) 时,会生成域模型的指令 处理器 。 指令处理器可以让用户轻松地访问模型,则会降低模板的需要编写程序集和导入指令中编写模板。
警告
在 演练:创建自定义文本模板宿主的本演练生成。执行该演练中的第一个。
本演练涵盖以下任务:
使用生成的 Domain-Specific Language Tools 基于域模型的指令处理器。
连接自定义文本模板宿主到生成的指令处理器。
测试已生成的指令处理器的自定义宿主。
系统必备
若要定义 DSL,必须安装以下组件:
Visual Studio |
|
Visual Studio SDK |
|
Visual Studio 可视化和建模 SDK |
此外,必须在 演练:创建自定义文本模板宿主创建的自定义文本模板转换。
使用生成域特定语言的工具指令处理器
在本演练中,您使用域特定语言设计器向导创建解决方案 DSLMinimalTest 的域特定语言 (dsl)。
使用域特定语言工具生成基于域模型的指令处理器
创建一个具有以下特征的一个域特定语言解决方案:
名称:DSLMinimalTest
解决方案模板:最小的语言
文件扩展名:分钟
公司名称:Fabrikam
有关创建特定于域的语言解决方案的更多信息,请参见 如何:创建域特定语言解决方案。
在**“生成”菜单上,单击“生成解决方案”**。
重要
此步骤生成指令处理器并将它的键在注册表。
在**“调试”菜单上,单击“启动调试”**。
Visual Studio 第二个实例将打开。
在实验性生成,在 解决方案资源管理器,双击文件 sample.min。
文件将在设计器中打开。 通知模型有两个组件, ExampleElement1 和 ExampleElement2 及其之间的链接。
关闭 Visual Studio 的第二个实例。
保存解决方案,然后关闭域特定语言设计器。
连接自定义文本模板宿主到指令处理器
在生成指令处理器后,来将在 演练:创建自定义文本模板宿主创建的指令处理器和自定义文本模板宿主。
连接自定义文本模板宿主到生成的指令处理器
打开 CustomHost 解决方案。
在**“项目”菜单上,单击“添加引用”**。
添加引用 对话框打开时显示的 .NET 选项。
添加以下引用:
Microsoft.VisualStudio.Modeling.Sdk.11.0
Microsoft.VisualStudio.Modeling.Sdk.Diagrams.11.0
Microsoft.VisualStudio.TextTemplating.11.0
Microsoft.VisualStudio.TextTemplating.Interfaces.11.0
Microsoft.VisualStudio.TextTemplating.Modeling.11.0
Microsoft.VisualStudio.TextTemplating.VSHost.11.0
在 Program.cs 或 Module1.vb 的顶部,添加以下代码行:
using Microsoft.Win32;
Imports Microsoft.Win32
找到属性的 StandardAssemblyReferences代码,然后用以下代码替换它:
备注
在此步骤中,添加对该生成的指令处理器所需的程序集宿主将支持。
//the host can provide standard assembly references //the engine will use these references when compiling and //executing the generated transformation class //-------------------------------------------------------------- public IList<string> StandardAssemblyReferences { get { return new string[] { //if this host searches standard paths and the GAC //we can specify the assembly name like this: //"System" //since this host only resolves assemblies from the //fully qualified path and name of the assembly //this is a quick way to get the code to give us the //fully qualified path and name of the System assembly //--------------------------------------------------------- typeof(System.Uri).Assembly.Location, typeof(System.Uri).Assembly.Location, typeof(Microsoft.VisualStudio.Modeling.ModelElement).Assembly.Location, typeof(Microsoft.VisualStudio.Modeling.Diagrams.BinaryLinkShape).Assembly.Location, typeof(Microsoft.VisualStudio.TextTemplating.VSHost.ITextTemplating).Assembly.Location, typeof(Microsoft.VisualStudio.TextTemplating.VSHost.ModelingTextTransformation).Assembly.Location }; } }
查找函数的 ResolveDirectiveProcessor代码,然后用以下代码替换它:
重要
此代码包含硬编码对要连接到生成的指令处理器的名称。,它会在注册表中列出的所有指令处理器并尝试查找匹配情况下,您可以轻松地使此过程更加泛型。在这种情况下,宿主与所有生成的指令处理器一起使用。
//the engine calls this method based on the directives the user has //specified it in the text template //this method can be called 0, 1, or more times //--------------------------------------------------------------------- public Type ResolveDirectiveProcessor(string processorName) { //check the processor name, and if it is the name of the processor the //host wants to support, return the type of the processor //--------------------------------------------------------------------- if (string.Compare(processorName, "DSLMinimalTestDirectiveProcessor", StringComparison.InvariantCultureIgnoreCase) == 0) { try { string keyName = @"Software\Microsoft\VisualStudio\10.0Exp_Config\TextTemplating\DirectiveProcessors\DSLMinimalTestDirectiveProcessor"; using (RegistryKey specificKey = Registry.CurrentUser.OpenSubKey(keyName)) { if (specificKey != null) { List<string> names = new List<String>(specificKey.GetValueNames()); string classValue = specificKey.GetValue("Class") as string; if (!string.IsNullOrEmpty(classValue)) { string loadValue = string.Empty; System.Reflection.Assembly processorAssembly = null; if (names.Contains("Assembly")) { loadValue = specificKey.GetValue("Assembly") as string; if (!string.IsNullOrEmpty(loadValue)) { //the assembly must be installed in the GAC processorAssembly = System.Reflection.Assembly.Load(loadValue); } } else if (names.Contains("CodeBase")) { loadValue = specificKey.GetValue("CodeBase") as string; if (!string.IsNullOrEmpty(loadValue)) { //loading local assembly processorAssembly = System.Reflection.Assembly.LoadFrom(loadValue); } } if (processorAssembly == null) { throw new Exception("Directive Processor not found"); } Type processorType = processorAssembly.GetType(classValue); if (processorType == null) { throw new Exception("Directive Processor not found"); } return processorType; } } } } catch (Exception e) { //if the directive processor can not be found, throw an error throw new Exception("Directive Processor not found"); } } //if the directive processor is not one this host wants to support throw new Exception("Directive Processor not supported"); }
在**“文件”菜单上,单击“全部保存”**。
在**“生成”菜单上,单击“生成解决方案”**。
测试具有指令处理器的自定义宿主
若要测试自定义文本模板宿主,必须首先编写调用所生成的指令处理器的文本模板。 然后您运行自定义宿主,并向其传递要文本模板的名称,验证该指令正确处理。
创建文本模板测试自定义宿主
创建一个文本文件,并将其命名为 TestTemplateWithDP.tt。 可以使用任何文本编辑器,如 " 记事本 ",创建文件。
向文本文件中添加以下内容:
备注
文本模板的编程语言不必与自定义宿主。
Text Template Host Test <#@ template debug="true" inherits="Microsoft.VisualStudio.TextTemplating.VSHost.ModelingTextTransformation" #> <# //this is the call to the examplemodel directive in the generated directive processor #> <#@ DSLMinimalTest processor="DSLMinimalTestDirectiveProcessor" requires="fileName='<Your Path>\Sample.min'" provides="ExampleModel=ExampleModel" #> <# //uncomment this line to test that the host allows the engine to set the extension #> <# //@ output extension=".htm" #> <# //uncomment this line if you want to see the generated transformation class #> <# //System.Diagnostics.Debugger.Break(); #> <# //this code uses the results of the examplemodel directive #> <# foreach ( ExampleElement box in this.ExampleModel.Elements ) { WriteLine("Box: {0}", box.Name); foreach (ExampleElement linkedTo in box.Targets) { WriteLine("Linked to: {0}", linkedTo.Name); } foreach (ExampleElement linkedFrom in box.Sources) { WriteLine("Linked from: {0}", linkedFrom.Name); } WriteLine(""); } #>
Text Template Host Test <#@ template debug="true" language="VB" inherits="Microsoft.VisualStudio.TextTemplating.VSHost.ModelingTextTransformation" #> <# 'this is the call to the examplemodel directive in the generated directive processor #> <#@ DSLMinimalTest processor="DSLMinimalTestDirectiveProcessor" requires="fileName='<Your Path>\Sample.min'" provides="ExampleModel=ExampleModel" #> <# 'Uncomment this line to test that the host allows the engine to set the extension. #> <# '@ output extension=".htm" #> <# 'Uncomment this line if you want to see the generated transformation class. #> <# 'System.Diagnostics.Debugger.Break() #> <# 'this code uses the results of the examplemodel directive #> <# For Each box as ExampleElement In Me.ExampleModel.Elements WriteLine("Box: {0}", box.Name) For Each LinkedTo as ExampleElement In box.Targets WriteLine("Linked to: {0}", LinkedTo.Name) Next For Each LinkedFrom as ExampleElement In box.Sources WriteLine("Linked from: {0}", LinkedFrom.Name) Next WriteLine("") Next #>
在代码,请在 Sample.min 文件的路径。在第一个过程中创建的设计特定语言的替代 YOUR PATH 。
保存并关闭文件。
测试自定义宿主
打开命令提示符窗口。
为自定义宿主键入可执行文件的路径,但暂不要按 Enter。
例如,键入:
<YOUR PATH>CustomHost\bin\Debug\CustomHost.exe
备注
而不键入地址,可以在中浏览到 Windows 资源管理器的文件 CustomHost.exe,然后将该文件拖入命令提示符窗口。
键入一个空格。
键入文本模板文件的路径,然后按 Enter。
例如,键入:
<YOUR PATH>TestTemplateWithDP.txt
备注
而不键入地址,可以在中浏览到 Windows 资源管理器的文件 TestTemplateWithDP.txt,然后将该文件拖入命令提示符窗口。
自定义宿主应用程序运行,并且文本模板转换过程的开头。
在 Windows 资源管理器,浏览到包含 TestTemplateWithDP.txt 文件的文件夹。
该文件夹还包含文件 TestTemplateWithDP1.txt。
打开此文件可以查看文本模板转换的结果。
生成的文本输出的结果显示应如下所示:
Text Template Host Test Box: ExampleElement1 Linked to: ExampleElement2 Box: ExampleElement2 Linked from: ExampleElement1