Share via


演练:将主机连接至生成的指令处理器

可以编写拥有处理文本模板的宿主。 基本的自定义宿主在 演练:创建自定义文本模板宿主将演示。 可以扩展承载添加功能 (如生成多个输出的文件。

在本演练中,将展开自定义宿主,以便支持调用指令处理器的文本模板。 在定义域特定语言 (dsl) 时,会生成域模型的指令 处理器 。 指令处理器可以让用户轻松地访问模型,则会降低模板的需要编写程序集和导入指令中编写模板。

警告

演练:创建自定义文本模板宿主的本演练生成。执行该演练中的第一个。

本演练涵盖以下任务:

  • 使用生成的 Domain-Specific Language Tools 基于域模型的指令处理器。

  • 连接自定义文本模板宿主到生成的指令处理器。

  • 测试已生成的指令处理器的自定义宿主。

系统必备

若要定义 DSL,必须安装以下组件:

Visual Studio

https://go.microsoft.com/fwlink/?linkid=185579

Visual Studio SDK

https://go.microsoft.com/fwlink/?linkid=185580

Visual Studio 可视化和建模 SDK

https://go.microsoft.com/fwlink/?LinkID=186128

此外,必须在 演练:创建自定义文本模板宿主创建的自定义文本模板转换。

使用生成域特定语言的工具指令处理器

在本演练中,您使用域特定语言设计器向导创建解决方案 DSLMinimalTest 的域特定语言 (dsl)。

使用域特定语言工具生成基于域模型的指令处理器

  1. 创建一个具有以下特征的一个域特定语言解决方案:

    • 名称:DSLMinimalTest

    • 解决方案模板:最小的语言

    • 文件扩展名:分钟

    • 公司名称:Fabrikam

    有关创建特定于域的语言解决方案的更多信息,请参见 如何:创建域特定语言解决方案

  2. 在**“生成”菜单上,单击“生成解决方案”**。

    重要

    此步骤生成指令处理器并将它的键在注册表。

  3. 在**“调试”菜单上,单击“启动调试”**。

    Visual Studio 第二个实例将打开。

  4. 在实验性生成,在 解决方案资源管理器,双击文件 sample.min

    文件将在设计器中打开。 通知模型有两个组件, ExampleElement1 和 ExampleElement2 及其之间的链接。

  5. 关闭 Visual Studio 的第二个实例。 

  6. 保存解决方案,然后关闭域特定语言设计器。

连接自定义文本模板宿主到指令处理器

在生成指令处理器后,来将在 演练:创建自定义文本模板宿主创建的指令处理器和自定义文本模板宿主。

连接自定义文本模板宿主到生成的指令处理器

  1. 打开 CustomHost 解决方案。

  2. 在**“项目”菜单上,单击“添加引用”**。

    添加引用 对话框打开时显示的 .NET 选项。

  3. 添加以下引用:

    • 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

  4. 在 Program.cs 或 Module1.vb 的顶部,添加以下代码行:

    using Microsoft.Win32;
    
    Imports Microsoft.Win32
    
  5. 找到属性的 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
    
            };
        }
    }
    
  6. 查找函数的 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");
            }
    
  7. 在**“文件”菜单上,单击“全部保存”**。

  8. 在**“生成”菜单上,单击“生成解决方案”**。

测试具有指令处理器的自定义宿主

若要测试自定义文本模板宿主,必须首先编写调用所生成的指令处理器的文本模板。 然后您运行自定义宿主,并向其传递要文本模板的名称,验证该指令正确处理。

创建文本模板测试自定义宿主

  1. 创建一个文本文件,并将其命名为 TestTemplateWithDP.tt。 可以使用任何文本编辑器,如 " 记事本 ",创建文件。

  2. 向文本文件中添加以下内容:

    备注

    文本模板的编程语言不必与自定义宿主。

    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 
    #>
    
  3. 在代码,请在 Sample.min 文件的路径。在第一个过程中创建的设计特定语言的替代 YOUR PATH 。

  4. 保存并关闭文件。

测试自定义宿主

  1. 打开命令提示符窗口。

  2. 为自定义宿主键入可执行文件的路径,但暂不要按 Enter。

    例如,键入:

    <YOUR PATH>CustomHost\bin\Debug\CustomHost.exe

    备注

    而不键入地址,可以在中浏览到 Windows 资源管理器的文件 CustomHost.exe,然后将该文件拖入命令提示符窗口。

  3. 键入一个空格。

  4. 键入文本模板文件的路径,然后按 Enter。

    例如,键入:

    <YOUR PATH>TestTemplateWithDP.txt

    备注

    而不键入地址,可以在中浏览到 Windows 资源管理器的文件 TestTemplateWithDP.txt,然后将该文件拖入命令提示符窗口。

    自定义宿主应用程序运行,并且文本模板转换过程的开头。

  5. Windows 资源管理器,浏览到包含 TestTemplateWithDP.txt 文件的文件夹。

    该文件夹还包含文件 TestTemplateWithDP1.txt。

  6. 打开此文件可以查看文本模板转换的结果。

    生成的文本输出的结果显示应如下所示:

    Text Template Host Test
    
    
    Box: ExampleElement1
    Linked to: ExampleElement2
    
    Box: ExampleElement2
    Linked from: ExampleElement1
    

请参见

任务

演练:创建自定义文本模板宿主