Udostępnij za pośrednictwem


Instruktaż: Tworzenie procesor dyrektywy niestandardowe

Procesory dyrektywa pracy przez dodanie kodu do generowane klasy transformacji.Jeśli zadzwonisz dyrektywy z tekst szablonu, reszta kodu, napisany w szablonie tekstu może polegać na funkcje, które zawiera dyrektywy.

Można napisać własne niestandardowe procesorów w dyrektywie.Dzięki temu można dostosowywać szablony tekstu.Aby utworzyć niestandardowe procesora w dyrektywie, należy utworzyć klasy, która dziedziczy albo DirectiveProcessor lub RequiresProvidesDirectiveProcessor.

Zadania, które zostały przedstawione w tym instruktażu są następujące:

  • Tworzenie niestandardowych procesora w dyrektywie

  • Rejestrowanie dyrektywa procesora

  • Testowanie dyrektywa procesora

Wymagania wstępne

Do przeprowadzenia tego instruktażu będą potrzebne:

  • Visual Studio 2010

  • Visual Studio 2010 SDK

Tworzenie procesor dyrektywy niestandardowe

W tym instruktażu służy do tworzenia niestandardowych procesora w dyrektywie.Dodawanie niestandardowych dyrektywy, który odczytuje plik XML, przechowuje je w XmlDocument zmienną i udostępnia go za pośrednictwem właściwości.W sekcji "Badania procesor dyrektywy" tej właściwości w szablonie tekstu służy do uzyskania dostępu do pliku XML.

Wywołanie swoje niestandardowe dyrektywy wygląda następująco:

<#@ CoolDirective Processor="CustomDirectiveProcessor" FileName="<Your Path>DocFile.xml" #>

Niestandardowe procesora w dyrektywie dodaje zmiennej i właściwości do klas generowanych transformacji.Dyrektywy, że piszesz zastosowań System.CodeDom klasy do tworzenia, silnik są dodawane do klasy transformacji wygenerowany kod.System.CodeDom Klasy Tworzenie kodu albo Visual C# lub Visual Basic, w zależności od języka, określone w language parametr template dyrektywy.Język dyrektywa procesora i język szablonu tekst, który uzyskuje dostęp do procesora w dyrektywie nie muszą odpowiadać.

Kod, który tworzy dyrektywy wygląda następująco:

private System.Xml.XmlDocument document0Value;

public virtual System.Xml.XmlDocument Document0
{
  get
  {
    if ((this.document0Value == null))
    {
      this.document0Value = XmlReaderHelper.ReadXml(<FileNameParameterValue>);
    }
    return this.document0Value;
  }
}
Private document0Value As System.Xml.XmlDocument

Public Overridable ReadOnly Property Document0() As System.Xml.XmlDocument
    Get
        If (Me.document0Value Is Nothing) Then
            Me.document0Value = XmlReaderHelper.ReadXml(<FileNameParameterValue>)
        End If
        Return Me.document0Value
    End Get
End Property

Aby utworzyć niestandardowe procesora w dyrektywie

  1. W programie Visual Studio Tworzenie C# lub Visual Basic project biblioteki klasy o nazwie CustomDP.

    [!UWAGA]

    Jeśli chcesz zainstalować dyrektywa procesora na więcej niż jednym komputerze, jest lepiej jest używać Visual Studio Extension (VSIX) projektu i Dołącz do rozszerzenia pliku .pkgdef.Aby uzyskać więcej informacji, zobacz Wdrażanie procesor dyrektywy niestandardowe.

  2. Dodaj odwołania do tych zestawów:

    • Microsoft.VisualStudio.TextTemplating.11.0

    • Microsoft.VisualStudio.TextTemplating.Interfaces.11.0

  3. Zastąp kod w Class1 z następującego kodu.Ten kod definiuje klasę CustomDirectiveProcessor, która dziedziczy z DirectiveProcessor klasy i wdraża niezbędne metody.

    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
    
  4. Dla Visual Basic , otwórz Projekt menu, a następnie kliknij przycisk Właściwości CustomDP.Na aplikacji kartę w głównego obszaru nazw, usuń wartość domyślna, CustomDP.

  5. Na pliku menu, kliknij przycisk Zapisz wszystkie.

  6. Na budować menu, kliknij przycisk Roztwór budować.

Bb126542.collapse_all(pl-pl,VS.110).gifSkompiluj projekt

Skompiluj projekt.Na budować menu, kliknij przycisk Roztwór budować.

Rejestrowanie procesor dyrektywy

Zanim zadzwonisz dyrektywy z szablonu tekstu w Visual Studio, należy dodać klucz rejestru dla procesora w dyrektywie.

[!UWAGA]

Jeśli chcesz zainstalować dyrektywa procesora na więcej niż jednym komputerze, to lepiej zdefiniować Visual Studio Extension (VSIX), który zawiera plik .pkgdef, wraz z zestawu sieci.Aby uzyskać więcej informacji, zobacz Wdrażanie procesor dyrektywy niestandardowe.

Klawisze służące do przetwórców dyrektywa istnieje w rejestrze w następującej lokalizacji:

HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\VisualStudio\11.0\TextTemplating\DirectiveProcessors

Dla 64-bitowych systemów jest lokalizacji rejestru:

HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Microsoft\VisualStudio\11.0\TextTemplating\DirectiveProcessors

W tej sekcji można dodać klucz dla niestandardowych dyrektywa procesora do rejestru w tej samej lokalizacji.

Informacje dotyczące przestrogiPrzestroga

Niepoprawne edytowanie rejestru może spowodować poważne uszkodzenie systemu.Przed wprowadzeniem zmian w rejestrze wykonaj kopię zapasową wszystkich cennych danych, który znajduje się na komputerze.

Aby dodać klucz rejestru dla dyrektywy procesora

  1. Uruchom regedit poleceń za pomocą Start menu lub z wiersza polecenia.

  2. Przejdź do lokalizacji, HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\VisualStudio\11.0\TextTemplating\DirectiveProcessorsi kliknij węzeł.

    W systemach 64-bitowe należy używaćHKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Microsoft\VisualStudio\11.0\TextTemplating\DirectiveProcessors

  3. Dodaj nowy klucz o nazwie CustomDirectiveProcessor.

    [!UWAGA]

    Jest to nazwa, która będzie używana w dziedzinie procesorów swoje niestandardowe dyrektyw.Tej nazwy nie musi odpowiadać nazwie dyrektywy, nazwa klasy dyrektywa procesora lub nazw procesora w dyrektywie.

  4. Dodaj nową wartość ciągu o nazwie klasy, która ma wartość CustomDP.CustomDirectiveProcessor dla nazwy nowy ciąg znaków.

  5. Dodaj nową wartość ciągu o nazwie CodeBase, która ma wartość równą ścieżki CustomDP.dll, który został utworzony wcześniej w tym instruktażu.

    Na przykład ścieżka może wyglądać C:\UserFiles\CustomDP\bin\Debug\CustomDP.dll.

    Klucz rejestru powinna mieć następujące wartości:

    Nazwa

    Typ

    Dane

    (Domyślnie)

    REG_SZ

    (wartość nieustalona)

    Klasa

    REG_SZ

    CustomDP.CustomDirectiveProcessor

    CodeBase

    REG_SZ

    CustomDP\bin\Debug\CustomDP.dll < ścieżka do rozwiązania >

    Jeśli umieścisz zestawu w pamięci podręcznej GAC, wartości powinny wyglądać następująco:

    Nazwa

    Typ

    Dane

    (Domyślnie)

    REG_SZ

    (wartość nieustalona)

    Klasa

    REG_SZ

    CustomDP.CustomDirectiveProcessor

    Montaż

    REG_SZ

    CustomDP.dll

  6. Uruchom ponownie program Visual Studio.

Testowanie procesor dyrektywy

Aby przetestować dyrektywa procesora, należy napisać szablon tekst, który wywołuje go.

W tym przykładzie szablonu tekst wywołuje dyrektywy i przechodzi w imieniu pliku XML, który zawiera plik klasy w dokumentacji.Aby uzyskać więcej informacji, zobacz Komentarzy dokumentacji XML (Podręcznik programowania C#).

Następnie używany w szablonie tekst XmlDocument właściwość, która dyrektywa tworzy przejdź do pliku XML i wydrukować komentarze dokumentacji.

Aby utworzyć plik XML do użycia w badaniach procesora w dyrektywie

  1. Utwórz plik tekstowy o nazwie DocFile.xml za pomocą dowolnego edytora tekstu (na przykład w Notatniku).

    [!UWAGA]

    Ten plik można utworzyć w dowolnym miejscu (na przykład C:\Test\DocFile.xml).

  2. Dodać następujący wpis do pliku tekstowego:

    <?xml version="1.0"?>
    <doc>
        <assembly>
            <name>xmlsample</name>
        </assembly>
        <members>
            <member name="T:SomeClass">
                <summary>Class level summary documentation goes here.</summary>
                <remarks>Longer comments can be associated with a type or member through the remarks tag</remarks>
            </member>
            <member name="F:SomeClass.m_Name">
                <summary>Store for the name property</summary>
            </member> 
            <member name="M:SomeClass.#ctor">
                <summary>The class constructor.</summary> 
            </member>
            <member name="M:SomeClass.SomeMethod(System.String)">
                <summary>Description for SomeMethod.</summary>
                <param name="s">Parameter description for s goes here</param>
                <seealso cref="T:System.String">You can use the cref attribute on any tag to reference a type or member and the compiler will check that the reference exists.</seealso>
            </member>
            <member name="M:SomeClass.SomeOtherMethod">
                <summary>Some other method.</summary>
                <returns>Return results are described through the returns tag.</returns>
                <seealso cref="M:SomeClass.SomeMethod(System.String)">Notice the use of the cref attribute to reference a specific method</seealso>
            </member>
            <member name="M:SomeClass.Main(System.String[])">
                <summary>The entry point for the application.</summary>
                <param name="args">A list of command line arguments</param>
            </member>
            <member name="P:SomeClass.Name">
                <summary>Name property</summary>
                <value>A value tag is used to describe the property value</value>
            </member>
        </members>
    </doc>
    
  3. Zapisz i zamknij plik.

Aby utworzyć szablon tekstu do testowania dyrektywa procesora

  1. W programie Visual Studio Tworzenie C# lub projektu biblioteki klas języka Visual Basic o nazwie TemplateTest.

  2. Dodaj nowy plik tekstowy szablon o nazwie TestDP.tt.

  3. Upewnij się, że Niestandardowego narzędzia właściwość TestDP.tt jest ustawiona na TextTemplatingFileGenerator.

  4. Zmień zawartość TestDP.tt na następujący tekst.

    [!UWAGA]

    Upewnij się zamienić ciąg <YOUR PATH> ze ścieżką do pliku DocFile.xml.

    Język szablonu tekst nie jest zgodny z językiem dyrektywa procesora.

    <#@ assembly name="System.Xml" #>
    <#@ template debug="true" #>
    <#@ output extension=".txt" #>
    
    <#  //This will call the custom directive processor. #>
    <#@ CoolDirective Processor="CustomDirectiveProcessor" FileName="<YOUR PATH>\DocFile.xml" #>
    
    <#  //Uncomment this line if you want to see the generated transformation class. #>
    <#  //System.Diagnostics.Debugger.Break(); #>
    
    <#  //This will use the results of the directive processor. #>
    <#  //The directive processor has read the XML and stored it in Document0. #>
    <#
        XmlNode node = Document0.DocumentElement.SelectSingleNode("members");
    
        foreach (XmlNode member in node.ChildNodes)
        {
            XmlNode name = member.Attributes.GetNamedItem("name");
            WriteLine("{0,7}:  {1}", "Name", name.Value);
    
            foreach (XmlNode comment in member.ChildNodes)
            {
                WriteLine("{0,7}:  {1}", comment.Name, comment.InnerText);
            }
            WriteLine("");
        }
    #>
    
    <#  //You can call the directive processor again and pass it a different file. #>
    <# //@ CoolDirective Processor="CustomDirectiveProcessor" FileName="<YOUR PATH>\<Your Second File>" #>
    
    <#  //To use the results of the second directive call, use Document1. #>
    <#
        //XmlNode node2 = Document1.DocumentElement.SelectSingleNode("members");
    
        //...
    #>
    
    <#@ assembly name="System.Xml" #>
    <#@ template debug="true" language="vb" #>
    <#@ output extension=".txt" #>
    
    <#  'This will call the custom directive processor. #>
    <#@ CoolDirective Processor="CustomDirectiveProcessor" FileName="<YOUR PATH>\DocFile.xml" #>
    
    <#  'Uncomment this line if you want to see the generated transformation class. #>
    <#  'System.Diagnostics.Debugger.Break() #>
    
    <#  'This will use the results of the directive processor. #>
    <#  'The directive processor has read the XML and stored it in Document0. #>
    <#
        Dim node as XmlNode = Document0.DocumentElement.SelectSingleNode("members")
    
        Dim member As XmlNode
        For Each member In node.ChildNodes
    
            Dim name As XmlNode = member.Attributes.GetNamedItem("name")
            WriteLine("{0,7}:  {1}", "Name", name.Value)
    
            Dim comment As XmlNode
            For Each comment In member.ChildNodes
                WriteLine("{0,7}:  {1}", comment.Name, comment.InnerText)
            Next
    
            WriteLine("")
        Next
    #>
    
    <#  'You can call the directive processor again and pass it a different file. #>
    <# '@ CoolDirective Processor="CustomDirectiveProcessor" FileName="<YOUR PATH>\DocFileTwo.xml" #>
    
    <#  'To use the results of the second directive call, use Document1. #>
    <#
        'node = Document1.DocumentElement.SelectSingleNode("members")
    
        '...
    #>
    

    [!UWAGA]

    W tym przykładzie wartość Processor jest parametr CustomDirectiveProcessor.Wartość Processor parametru musi odpowiadać nazwie klucza rejestru procesora.

  5. Na pliku menu, kliknij przycisk Zapisz wszystkie.

Aby przetestować dyrektywa procesora

  1. W Solution Explorer, kliknij prawym przyciskiem myszy TestDP.tt, a następnie kliknij przycisk Uruchomić narzędzie niestandardowe.

    Dla Visual Basic użytkowników, TestDP.txt mogą nie być widoczne w Solution Explorer domyślnie.Aby wyświetlić wszystkie pliki, przypisany do projektu, należy otworzyć Projekt menu i kliknij przycisk Pokaż wszystkie pliki.

  2. W Solution Explorer, rozwiń węzeł TestDP.txt, a następnie kliknij dwukrotnie TestDP.txt, aby go otworzyć w edytorze.

    Tekst wygenerowany dane wyjściowe są wyświetlane.Dane wyjściowe powinny wyglądać następująco:

       Name:  T:SomeClass
    summary:  Class level summary documentation goes here.
    remarks:  Longer comments can be associated with a type or member through the remarks tag
    
       Name:  F:SomeClass.m_Name
    summary:  Store for the name property
    
       Name:  M:SomeClass.#ctor
    summary:  The class constructor.
    
       Name:  M:SomeClass.SomeMethod(System.String)
    summary:  Description for SomeMethod.
      param:  Parameter description for s goes here
    seealso:  You can use the cref attribute on any tag to reference a type or member and the compiler will check that the reference exists.
    
       Name:  M:SomeClass.SomeOtherMethod
    summary:  Some other method.
    returns:  Return results are described through the returns tag.
    seealso:  Notice the use of the cref attribute to reference a specific method
    
       Name:  M:SomeClass.Main(System.String[])
    summary:  The entry point for the application.
      param:  A list of command line arguments
    
       Name:  P:SomeClass.Name
    summary:  Name property
      value:  A value tag is used to describe the property value
    

Dodawanie HTML wygenerowany tekst

Po przetestowaniu procesorów dyrektywa niestandardowe chcesz dodać kod HTML wygenerowany tekst.

Aby dodać HTML do wygenerowanego tekstu

  1. Zastąp kod w TestDP.tt poniżej.HTML jest podświetlony.Upewnij się zamienić ciąg YOUR PATH ze ścieżką do pliku DocFile.xml.

    [!UWAGA]

    Otwórz dodatkowe < # i # ścisłej > znaczniki oddzielne kodu instrukcji z tagów HTML.

    <#@ assembly name="System.Xml" #>
    <#@ template debug="true" #>
    <#@ output extension=".htm" #>
    
    <#  //this will call the custom directive processor #>
    <#@ CoolDirective Processor="CustomDirectiveProcessor" FileName="<YOUR PATH>\DocFile.xml" #>
    
    <#  //uncomment this line if you want to see the generated transformation class #>
    <#  //System.Diagnostics.Debugger.Break(); #>
    
    <html>
    <body>
    
    <#  //this will use the results of the directive processor #>
    <#  //the directive processor has read the XML and stored it in Document0#>
    <#
        XmlNode node = Document0.DocumentElement.SelectSingleNode("members");
    
        foreach (XmlNode member in node.ChildNodes)
        {
    #>
    <h3>
    <#    
            XmlNode name = member.Attributes.GetNamedItem("name");
            WriteLine("{0,7}:  {1}", "Name", name.Value);
    #>
    </h3>
    <#
            foreach (XmlNode comment in member.ChildNodes)
            {
                WriteLine("{0,7}:  {1}", comment.Name, comment.InnerText);
    #>
    <br/>
    <#
            }
        }
    #>
    </body>
    </html>
    
    <#@ assembly name="System.Xml" #>
    <#@ template debug="true" language="vb" #>
    <#@ output extension=".htm" #>
    
    <#  'this will call the custom directive processor #>
    <#@ CoolDirective Processor="CustomDirectiveProcessor" FileName="<YOUR PATH>\DocFile.xml" #>
    
    <#  'uncomment this line if you want to see the generated transformation class #>
    <#  'System.Diagnostics.Debugger.Break() #>
    
    <html>
    <body>
    
    <#  'this will use the results of the directive processor #>
    <#  'the directive processor has read the XML and stored it in Document0#>
    <#
        Dim node as XmlNode = Document0.DocumentElement.SelectSingleNode("members")
    
        Dim member As XmlNode
        For Each member In node.ChildNodes
    #>
    <h3>
    <#    
            Dim name As XmlNode = member.Attributes.GetNamedItem("name")
            WriteLine("{0,7}:  {1}", "Name", name.Value)
    #>
    </h3>
    <#
            Dim comment As XmlNode
            For Each comment In member.ChildNodes
                WriteLine("{0,7}:  {1}", comment.Name, comment.InnerText)
    #>
    <br/>
    <#
            Next
        Next
    #>
    </body>
    </html>
    
  2. Na pliku menu, kliknij przycisk Zapisać TestDP.txt.

  3. Aby wyświetlić dane wyjściowe w przeglądarce, w Solution Explorer, a następnie kliknij prawym przyciskiem myszy TestDP.htm i kliknij przycisk Widok W przeglądarce,.

    Dane wyjściowe powinien być taki sam jak oryginalny tekst, z wyjątkiem powinna mieć format HTML, zastosowany.Każda nazwa towaru powinny są pogrubione.