逐步解說:將主機連線至產生的指示詞處理器

您可以撰寫處理文字範本的主機。 基本自訂主應用程式示範於逐步解說:建立自訂文字範本主機。 您可以擴充該主機以新增函式,例如產生多個輸出檔案。

在本逐步解說中,您會擴充自訂主應用程式,使其支援呼叫指示詞處理器的文字範本。 當您定義特定領域語言時,它會為領域模型產生指示詞處理器。 指示詞處理器可讓使用者更輕鬆地撰寫可存取模型的範本,減少在範本中撰寫組件和匯入指示詞的需求。

注意

本逐步解說是以逐步解說:建立自訂文字範本主機為基礎所建置。 請先執行該逐步解說。

本逐步解說包含下列工作:

  • 使用特定領域語言工具來產生以領域模型為基礎的指示詞處理器。

  • 將自訂文字範本主機連線到產生的指示詞處理器。

  • 使用產生的指示詞處理器測試自訂主應用程式。

必要條件

若要定義 DSL,您必須已安裝下列元件:

元件 連結
Visual Studio http://go.microsoft.com/fwlink/?LinkId=185579
Visual Studio SDK http://go.microsoft.com/fwlink/?LinkId=185580
Visual Studio Visualization and Modeling SDK

注意

文字範本轉換元件會作為 Visual Studio 延伸模組開發工作負載的一部分自動安裝。 您也可以從 Visual Studio 安裝程式的 [個別元件] 索引標籤加以安裝,其位於 [SDK、程式庫和架構] 底下。 從 [個別元件] 索引標籤安裝 Modeling SDK 元件。

此外,您必須在逐步解說:建立自訂文字模板主機中建立自訂文字範本轉換。

使用特定領域語言工具來產生指示詞處理器

在本逐步解說中,您會使用特定領域語言設計工具精靈來建立解決方案 DSLMinimalTest 的特定領域語言。

  1. 建立具有下列特性的特定領域語言解決方案:

    • 名稱:DSLMinimalTest

    • 解決方案範本:最低語言

    • 副檔名:min

    • 公司名稱: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;
    
  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("");
        }
    #>
    
  3. 在程式碼中,將 <YOUR PATH> 取代為您在第一個程序中所建立特定設計語言的 Sample.min 檔案路徑。

  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