共用方式為


DirectiveProcessor 類別

具體指示詞處理器的抽象基底類別。

繼承階層架構

System.Object
  Microsoft.VisualStudio.TextTemplating.DirectiveProcessor
    Microsoft.VisualStudio.TextTemplating.ParameterDirectiveProcessor
    Microsoft.VisualStudio.TextTemplating.RequiresProvidesDirectiveProcessor

命名空間:  Microsoft.VisualStudio.TextTemplating
組件:  Microsoft.VisualStudio.TextTemplating.11.0 (在 Microsoft.VisualStudio.TextTemplating.11.0.dll 中)

語法

'宣告
Public MustInherit Class DirectiveProcessor _
    Implements IDirectiveProcessor
public abstract class DirectiveProcessor : IDirectiveProcessor
public ref class DirectiveProcessor abstract : IDirectiveProcessor
[<AbstractClass>]
type DirectiveProcessor =  
    class
        interface IDirectiveProcessor
    end
public abstract class DirectiveProcessor implements IDirectiveProcessor

DirectiveProcessor 型別會公開下列成員。

建構函式

  名稱 說明
受保護的方法 DirectiveProcessor 在衍生類別中覆寫時,初始化 DirectiveProcessor 類別的新執行個體。

回頁首

屬性

  名稱 說明
受保護的屬性 Errors 取得發生錯誤,便會處理指示詞時的錯誤。

回頁首

方法

  名稱 說明
公用方法 Equals 判斷指定的物件是否等於目前物件。 (繼承自 Object)。
受保護的方法 Finalize 允許物件在記憶體回收進行回收之前,嘗試釋放資源並執行其他清除作業。 (繼承自 Object)。
公用方法 FinishProcessingRun 在衍生類別中覆寫時,完成一輪指示詞處理。
公用方法 GetClassCodeForProcessingRun 在衍生類別中覆寫時,取得程式碼以加入至所產生的轉換類別。
公用方法 GetHashCode 做為特定型別的雜湊函式。 (繼承自 Object)。
公用方法 GetImportsForProcessingRun 在衍生類別中覆寫時,取得命名空間以匯入所產生的轉換類別中。
公用方法 GetPostInitializationCodeForProcessingRun 在衍生類別中覆寫時,取得程式碼以加入至所產生轉換類別的 Initialize 方法結尾。
公用方法 GetPreInitializationCodeForProcessingRun 當在衍生類別中覆寫時,取得程式碼加入至產生的轉換類別的初始設定方法的開頭。
公用方法 GetReferencesForProcessingRun 在衍生類別中覆寫時,取得參考以傳遞至所產生的轉換類別編譯器。
公用方法 GetTemplateClassCustomAttributes 取得所有自訂屬性將樣板類別。
公用方法 GetType 取得目前執行個體的 Type。 (繼承自 Object)。
公用方法 Initialize 在衍生類別中覆寫時,初始化處理器執行個體。
公用方法 IsDirectiveSupported 當在衍生類別中覆寫時,判斷指示詞處理器是否支援指定的指示詞。
受保護的方法 MemberwiseClone 建立目前 Object 的淺層複本 (Shallow Copy)。 (繼承自 Object)。
公用方法 ProcessDirective 在衍生類別中覆寫時,處理範本檔中的單一指示詞。
公用方法 StartProcessingRun 當在衍生類別中覆寫時,開始回合指示詞處理器。
公用方法 ToString 傳回表示目前物件的字串。 (繼承自 Object)。

回頁首

明確介面實作

  名稱 說明
明確介面實作私用屬性 IDirectiveProcessor.Errors
明確介面實作私用屬性 IDirectiveProcessor.RequiresProcessingRunIsHostSpecific
明確介面實作私用方法 IDirectiveProcessor.SetProcessingRunIsHostSpecific

回頁首

備註

文字範本轉換處理序有兩個步驟。在第一個步驟中,文字範本轉換引擎會建立做為所產生的轉換類別之參考的類別。在第二個步驟中,引擎會編譯並執行所產生的轉換類別,以產生所產生的文字輸出。

在「產生的轉換類別」(Generated Transformation Class) 中加入程式碼,即可讓「指示詞處理器」(Directive Processor) 運作。您可以從文字範本呼叫指示詞,而在呼叫指示詞之後,您在文字範本中撰寫的其餘程式碼部分就可以使用由指示詞所提供的功能。您可以撰寫您自己的自訂指示詞處理器,以提供文字範本的自訂功能。

如需詳細資訊,請參閱 建立自訂 T4 文字範本指示詞處理器

文字範本轉換引擎會保留任何必要的 DirectiveProcessor 類別的單一執行個體。

DirectiveProcessor 會實作狀態機器。

例如,如果文字範本對同一個指示詞處理器發出三個指示詞呼叫,引擎會依下列順序呼叫方法:

範例

下列範例會建立自訂的指示詞處理器。自訂的指示詞處理器包含讀取 XML 檔案的指示詞。指示詞將 XML 儲存在一個 XmlDocument 變數中,並透過屬性公開 XmlDocument

如需詳細資訊,請參閱逐步解說:建立自訂指示詞處理器

using System;
using System.CodeDom;
using System.CodeDom.Compiler;
using System.Collections.Generic;
using System.Globalization;
using System.IO;
using System.Text;
using System.Xml;
using System.Xml.Serialization;
using Microsoft.VisualStudio.TextTemplating;

namespace CustomDP
{
    public class CustomDirectiveProcessor : DirectiveProcessor
    {
        //this buffer stores the code that is added to the 
        //generated transformation class after all the processing is done 
        //---------------------------------------------------------------------
        private StringBuilder codeBuffer;


        //Using a Code Dom Provider creates code for the 
        //generated transformation class in either Visual Basic or C#.
        //If you want your directive processor to support only one language, you
        //can hard code the code you add to the generated transformation class.
        //In that case, you do not need this field.
        //--------------------------------------------------------------------------
        private CodeDomProvider codeDomProvider;


        //this stores the full contents of the text template that is being processed
        //--------------------------------------------------------------------------
        private String templateContents;


        //These are the errors that occur during processing. The engine passes 
        //the errors to the host, and the host can decide how to display them,
        //for example the the host can display the errors in the UI
        //or write them to a file.
        //---------------------------------------------------------------------
        private CompilerErrorCollection errorsValue;
        public new CompilerErrorCollection Errors
        {
            get { return errorsValue; }
        }


        //Each time this directive processor is called, it creates a new property.
        //We count how many times we are called, and append "n" to each new
        //property name. The property names are therefore unique.
        //-----------------------------------------------------------------------------
        private int directiveCount = 0;


        public override void Initialize(ITextTemplatingEngineHost host)
        {
            //we do not need to do any initialization work
        }


        public override void StartProcessingRun(CodeDomProvider languageProvider, String templateContents, CompilerErrorCollection errors)
        {
            //the engine has passed us the language of the text template
            //we will use that language to generate code later
            //----------------------------------------------------------
            this.codeDomProvider = languageProvider;
            this.templateContents = templateContents;
            this.errorsValue = errors;

            this.codeBuffer = new StringBuilder();
        }


        //Before calling the ProcessDirective method for a directive, the 
        //engine calls this function to see whether the directive is supported.
        //Notice that one directive processor might support many directives.
        //---------------------------------------------------------------------
        public override bool IsDirectiveSupported(string directiveName)
        {
            if (string.Compare(directiveName, "CoolDirective", StringComparison.OrdinalIgnoreCase) == 0)
            {
                return true;
            }
            if (string.Compare(directiveName, "SuperCoolDirective", StringComparison.OrdinalIgnoreCase) == 0)
            {
                return true;
            }
            return false;
        }


        public override void ProcessDirective(string directiveName, IDictionary<string, string> arguments)
        {
            if (string.Compare(directiveName, "CoolDirective", StringComparison.OrdinalIgnoreCase) == 0)
            {
                string fileName;

                if (!arguments.TryGetValue("FileName", out fileName))
                {
                    throw new DirectiveProcessorException("Required argument 'FileName' not specified.");
                }

                if (string.IsNullOrEmpty(fileName))
                {
                    throw new DirectiveProcessorException("Argument 'FileName' is null or empty.");
                }

                //Now we add code to the generated transformation class.
                //This directive supports either Visual Basic or C#, so we must use the
                //System.CodeDom to create the code.
                //If a directive supports only one language, you can hard code the code.
                //--------------------------------------------------------------------------

                CodeMemberField documentField = new CodeMemberField();

                documentField.Name = "document" + directiveCount + "Value";
                documentField.Type = new CodeTypeReference(typeof(XmlDocument));
                documentField.Attributes = MemberAttributes.Private;

                CodeMemberProperty documentProperty = new CodeMemberProperty();

                documentProperty.Name = "Document" + directiveCount;
                documentProperty.Type = new CodeTypeReference(typeof(XmlDocument));
                documentProperty.Attributes = MemberAttributes.Public;
                documentProperty.HasSet = false;
                documentProperty.HasGet = true;

                CodeExpression fieldName = new CodeFieldReferenceExpression(new CodeThisReferenceExpression(), documentField.Name);
                CodeExpression booleanTest = new CodeBinaryOperatorExpression(fieldName, CodeBinaryOperatorType.IdentityEquality, new CodePrimitiveExpression(null));
                CodeExpression rightSide = new CodeMethodInvokeExpression(new CodeTypeReferenceExpression("XmlReaderHelper"), "ReadXml", new CodePrimitiveExpression(fileName));
                CodeStatement[] thenSteps = new CodeStatement[] { new CodeAssignStatement(fieldName, rightSide) };

                CodeConditionStatement ifThen = new CodeConditionStatement(booleanTest, thenSteps);
                documentProperty.GetStatements.Add(ifThen);

                CodeStatement s = new CodeMethodReturnStatement(fieldName);
                documentProperty.GetStatements.Add(s);

                CodeGeneratorOptions options = new CodeGeneratorOptions();
                options.BlankLinesBetweenMembers = true;
                options.IndentString = "    ";
                options.VerbatimOrder = true;
                options.BracingStyle = "C";

                using (StringWriter writer = new StringWriter(codeBuffer, CultureInfo.InvariantCulture))
                {
                    codeDomProvider.GenerateCodeFromMember(documentField, writer, options);
                    codeDomProvider.GenerateCodeFromMember(documentProperty, writer, options);
                }

            }//end CoolDirective


            //One directive processor can contain many directives.
            //If you want to support more directives, the code goes here...
            //-----------------------------------------------------------------
            if (string.Compare(directiveName, "supercooldirective", StringComparison.OrdinalIgnoreCase) == 0)
            {
                //code for SuperCoolDirective goes here...
            }//end SuperCoolDirective


            //Track how many times the processor has been called.
            //-----------------------------------------------------------------
            directiveCount++;

        }//end ProcessDirective


        public override void FinishProcessingRun()
        {
            this.codeDomProvider = null;

            //important: do not do this:
            //the get methods below are called after this method 
            //and the get methods can access this field
            //-----------------------------------------------------------------
            //this.codeBuffer = null;
        }


        public override string GetPreInitializationCodeForProcessingRun()
        {
            //Use this method to add code to the start of the 
            //Initialize() method of the generated transformation class.
            //We do not need any pre-initialization, so we will just return "".
            //-----------------------------------------------------------------
            //GetPreInitializationCodeForProcessingRun runs before the 
            //Initialize() method of the base class.
            //-----------------------------------------------------------------
            return String.Empty;
        }


        public override string GetPostInitializationCodeForProcessingRun()
        {
            //Use this method to add code to the end of the 
            //Initialize() method of the generated transformation class.
            //We do not need any post-initialization, so we will just return "".
            //------------------------------------------------------------------
            //GetPostInitializationCodeForProcessingRun runs after the
            //Initialize() method of the base class.
            //-----------------------------------------------------------------
            return String.Empty;
        }


        public override string GetClassCodeForProcessingRun()
        {
            //Return the code to add to the generated transformation class.
            //-----------------------------------------------------------------
            return codeBuffer.ToString();
        }


        public override string[] GetReferencesForProcessingRun()
        {
            //This returns the references that we want to use when 
            //compiling the generated transformation class.
            //-----------------------------------------------------------------
            //We need a reference to this assembly to be able to call 
            //XmlReaderHelper.ReadXml from the generated transformation class.
            //-----------------------------------------------------------------
            return new string[]
            {
                "System.Xml",
                this.GetType().Assembly.Location
            };
        }


        public override string[] GetImportsForProcessingRun()
        {
            //This returns the imports or using statements that we want to 
            //add to the generated transformation class.
            //-----------------------------------------------------------------
            //We need CustomDP to be able to call XmlReaderHelper.ReadXml
            //from the generated transformation class.
            //-----------------------------------------------------------------
            return new string[]
            {
                "System.Xml",
                "CustomDP"
            };
        }
    }//end class CustomDirectiveProcessor


    //-------------------------------------------------------------------------
    // the code that we are adding to the generated transformation class 
    // will call this method
    //-------------------------------------------------------------------------
    public static class XmlReaderHelper
    {
        public static XmlDocument ReadXml(string fileName)
        {
            XmlDocument d = new XmlDocument();

            using (XmlTextReader reader = new XmlTextReader(fileName))
            {
                try
                {
                    d.Load(reader);
                }
                catch (System.Xml.XmlException e)
                {
                    throw new DirectiveProcessorException("Unable to read the XML file.", e);
                }
            }
            return d;
        }
    }//end class XmlReaderHelper
}//end namespace CustomDP
Imports System
Imports System.CodeDom
Imports System.CodeDom.Compiler
Imports System.Collections.Generic
Imports System.Globalization
Imports System.IO
Imports System.Text
Imports System.Xml
Imports System.Xml.Serialization
Imports Microsoft.VisualStudio.TextTemplating

Namespace CustomDP

    Public Class CustomDirectiveProcessor
    Inherits DirectiveProcessor

        'this buffer stores the code that is added to the 
        'generated transformation class after all the processing is done 
        '---------------------------------------------------------------
        Private codeBuffer As StringBuilder


        'Using a Code Dom Provider creates code for the
        'generated transformation class in either Visual Basic or C#.
        'If you want your directive processor to support only one language, you
        'can hard code the code you add to the generated transformation class.
        'In that case, you do not need this field.
        '--------------------------------------------------------------------------
        Private codeDomProvider As CodeDomProvider


        'this stores the full contents of the text template that is being processed
        '--------------------------------------------------------------------------
        Private templateContents As String


        'These are the errors that occur during processing. The engine passes 
        'the errors to the host, and the host can decide how to display them,
        'for example the the host can display the errors in the UI
        'or write them to a file.
        '---------------------------------------------------------------------
        Private errorsValue As CompilerErrorCollection
        Public Shadows ReadOnly Property Errors() As CompilerErrorCollection
            Get
                Return errorsValue
            End Get
        End Property


        'Each time this directive processor is called, it creates a new property.
        'We count how many times we are called, and append "n" to each new
        'property name. The property names are therefore unique.
        '--------------------------------------------------------------------------
        Private directiveCount As Integer = 0


        Public Overrides Sub Initialize(ByVal host As ITextTemplatingEngineHost)

            'we do not need to do any initialization work
        End Sub


        Public Overrides Sub StartProcessingRun(ByVal languageProvider As CodeDomProvider, ByVal templateContents As String, ByVal errors As CompilerErrorCollection)

            'the engine has passed us the language of the text template
            'we will use that language to generate code later
            '----------------------------------------------------------
            Me.codeDomProvider = languageProvider
            Me.templateContents = templateContents
            Me.errorsValue = errors

            Me.codeBuffer = New StringBuilder()
        End Sub


        'Before calling the ProcessDirective method for a directive, the 
        'engine calls this function to see whether the directive is supported.
        'Notice that one directive processor might support many directives.
        '---------------------------------------------------------------------
        Public Overrides Function IsDirectiveSupported(ByVal directiveName As String) As Boolean

            If String.Compare(directiveName, "CoolDirective", StringComparison.OrdinalIgnoreCase) = 0 Then
                Return True
            End If

            If String.Compare(directiveName, "SuperCoolDirective", StringComparison.OrdinalIgnoreCase) = 0 Then
                Return True
            End If

            Return False
        End Function


        Public Overrides Sub ProcessDirective(ByVal directiveName As String, ByVal arguments As IDictionary(Of String, String))

            If String.Compare(directiveName, "CoolDirective", StringComparison.OrdinalIgnoreCase) = 0 Then

                Dim fileName As String

                If Not (arguments.TryGetValue("FileName", fileName)) Then
                    Throw New DirectiveProcessorException("Required argument 'FileName' not specified.")
                End If

                If String.IsNullOrEmpty(fileName) Then
                    Throw New DirectiveProcessorException("Argument 'FileName' is null or empty.")
                End If

                'Now we add code to the generated transformation class.
                'This directive supports either Visual Basic or C#, so we must use the
                'System.CodeDom to create the code.
                'If a directive supports only one language, you can hard code the code.
                '--------------------------------------------------------------------------

                Dim documentField As CodeMemberField = New CodeMemberField()

                documentField.Name = "document" & directiveCount & "Value"
                documentField.Type = New CodeTypeReference(GetType(XmlDocument))
                documentField.Attributes = MemberAttributes.Private

                Dim documentProperty As CodeMemberProperty = New CodeMemberProperty()

                documentProperty.Name = "Document" & directiveCount
                documentProperty.Type = New CodeTypeReference(GetType(XmlDocument))
                documentProperty.Attributes = MemberAttributes.Public
                documentProperty.HasSet = False
                documentProperty.HasGet = True

                Dim fieldName As CodeExpression = New CodeFieldReferenceExpression(New CodeThisReferenceExpression(), documentField.Name)
                Dim booleanTest As CodeExpression = New CodeBinaryOperatorExpression(fieldName, CodeBinaryOperatorType.IdentityEquality, New CodePrimitiveExpression(Nothing))
                Dim rightSide As CodeExpression = New CodeMethodInvokeExpression(New CodeTypeReferenceExpression("XmlReaderHelper"), "ReadXml", New CodePrimitiveExpression(fileName))
                Dim thenSteps As CodeStatement() = New CodeStatement() {New CodeAssignStatement(fieldName, rightSide)}

                Dim ifThen As CodeConditionStatement = New CodeConditionStatement(booleanTest, thenSteps)
                documentProperty.GetStatements.Add(ifThen)

                Dim s As CodeStatement = New CodeMethodReturnStatement(fieldName)
                documentProperty.GetStatements.Add(s)

                Dim options As CodeGeneratorOptions = New CodeGeneratorOptions()
                options.BlankLinesBetweenMembers = True
                options.IndentString = "    "
                options.VerbatimOrder = True
                options.BracingStyle = "VB"

                Using writer As StringWriter = New StringWriter(codeBuffer, CultureInfo.InvariantCulture)

                    codeDomProvider.GenerateCodeFromMember(documentField, writer, options)
                    codeDomProvider.GenerateCodeFromMember(documentProperty, writer, options)
                End Using

            End If  'CoolDirective


            'One directive processor can contain many directives.
            'If you want to support more directives, the code goes here...
            '-----------------------------------------------------------------
            If String.Compare(directiveName, "supercooldirective", StringComparison.OrdinalIgnoreCase) = 0 Then

                'code for SuperCoolDirective goes here
            End If 'SuperCoolDirective

            'Track how many times the processor has been called.
            '-----------------------------------------------------------------
            directiveCount += 1
        End Sub 'ProcessDirective


        Public Overrides Sub FinishProcessingRun()

            Me.codeDomProvider = Nothing

            'important: do not do this:
            'the get methods below are called after this method 
            'and the get methods can access this field
            '-----------------------------------------------------------------
            'Me.codeBuffer = Nothing
        End Sub


        Public Overrides Function GetPreInitializationCodeForProcessingRun() As String

            'Use this method to add code to the start of the 
            'Initialize() method of the generated transformation class.
            'We do not need any pre-initialization, so we will just return "".
            '-----------------------------------------------------------------
            'GetPreInitializationCodeForProcessingRun runs before the 
            'Initialize() method of the base class.
            '-----------------------------------------------------------------
            Return String.Empty
        End Function


        Public Overrides Function GetPostInitializationCodeForProcessingRun() As String

            'Use this method to add code to the end of the 
            'Initialize() method of the generated transformation class.
            'We do not need any post-initialization, so we will just return "".
            '------------------------------------------------------------------
            'GetPostInitializationCodeForProcessingRun runs after the
            'Initialize() method of the base class.
            '-----------------------------------------------------------------
            Return String.Empty
        End Function


        Public Overrides Function GetClassCodeForProcessingRun() As String

            'Return the code to add to the generated transformation class.
            '-----------------------------------------------------------------
            Return codeBuffer.ToString()
        End Function


        Public Overrides Function GetReferencesForProcessingRun() As String()

            'This returns the references that we want to use when 
            'compiling the generated transformation class.
            '-----------------------------------------------------------------
            'We need a reference to this assembly to be able to call 
            'XmlReaderHelper.ReadXml from the generated transformation class.
            '-----------------------------------------------------------------
            Return New String() {"System.Xml", Me.GetType().Assembly.Location}
        End Function


        Public Overrides Function GetImportsForProcessingRun() As String()

            'This returns the imports or using statements that we want to 
            'add to the generated transformation class.
            '-----------------------------------------------------------------
            'We need CustomDP to be able to call XmlReaderHelper.ReadXml
            'from the generated transformation class.
            '-----------------------------------------------------------------
            Return New String() {"System.Xml", "CustomDP"}
        End Function
    End Class 'CustomDirectiveProcessor


    '--------------------------------------------------------------------------
    ' the code that we are adding to the generated transformation class 
    ' will call this method
    '--------------------------------------------------------------------------
    Public Class XmlReaderHelper

        Public Shared Function ReadXml(ByVal fileName As String) As XmlDocument

            Dim d As XmlDocument = New XmlDocument()

            Using reader As XmlTextReader = New XmlTextReader(fileName)

                Try
                    d.Load(reader)

                Catch e As System.Xml.XmlException

                    Throw New DirectiveProcessorException("Unable to read the XML file.", e)
                End Try
            End Using

            Return d
        End Function
    End Class 'XmlReaderHelper

End Namespace

執行緒安全

這個型別的任何 Public static (在 Visual Basic 中為 Shared) 成員都具備執行緒安全。不保證任何執行個體成員是安全執行緒。

請參閱

參考

Microsoft.VisualStudio.TextTemplating 命名空間

RequiresProvidesDirectiveProcessor

其他資源

建立自訂 T4 文字範本指示詞處理器

逐步解說:建立自訂指示詞處理器