Share via


Walkthrough: Creating a Generated API

In this walkthrough, you create a generated API for a domain-specific language. To create the domain-specific language, you use the XML for a sample domain model that is called Library. After you generate the API, you can use it as a reference for the sections within Understanding the Generated Code. Library.Dsl Overview describes the generated API that you create in this walkthrough.

Note

In this walkthrough, you create a domain-specific language by copying the XML for the Library domain model into a .dsl file. However, you typically create a domain-specific language by using the Domain-Specific Language Designer Wizard. For more information about how to use this wizard, see Walkthrough: Creating a Domain-Specific Language Solution.

Creating the Domain-Specific Language

To create a domain-specific language

  1. On the File menu, point to New, and then click Project.

    The New Project dialog box appears.

  2. Under Project types, click Visual C#.

  3. Under Visual Studio installed templates, click Class Library.

  4. In Name, type GenFromModel, and click OK.

  5. In Solution Explorer, delete the file Class1.cs so that you start with an empty project.

  6. On the Project menu, click Add Reference.

    The Add Reference dialog box opens with the .NET tab displayed.

  7. In the Component Name column, click the following references:

    • Microsoft.VisualStudio.Modeling.Sdk

    • Microsoft.VisualStudio.Modeling.Sdk.Diagrams

    • System.Drawing

  8. Click OK.

    The references are added to the project.

  9. On the Project menu, click Add New Item.

  10. Under Visual Studio installed templates, click Text File.

  11. In Name, type library.dsl, and click Add.

  12. On the File menu, click Close to close library.dsl.

  13. In Solution Explorer, right-click library.dsl, and click Open With.

  14. In the Open With dialog box, click XML Editor, and click OK.

  15. Copy and paste the following XML into the file, and then save it.

    <?xml version="1.0" encoding="utf-8"?>
    <Dsl dslVersion="1.0.0.0" Id="e4dcf5e5-aefc-468e-8d66-07b2e50d7c96" Description="Description for Microsoft.Language25.Language25" Name="ExampleModel" DisplayName="ExampleModel" Namespace="ExampleNamespace" PackageGuid="00000000-0000-0000-0000-000000000000" PackageNamespace="ExampleNamespace">
      <Classes>
        <DomainClass Id="eeb41517-6782-4ce3-bf8c-8f59a5f76998" Description="Description for ExampleNamespace.Library" Name="Library" DisplayName="Library" Namespace="ExampleNamespace">
          <Properties>
            <DomainProperty Id="fed0299c-1295-44e1-ba80-73d56d4e538f" Description="Description for ExampleNamespace.Library.Name" Name="Name" DisplayName="Name" DefaultValue="DefaultLibraryName" IsElementName="true">
              <Type>
                <ExternalTypeMoniker Name="/System/String" />
              </Type>
            </DomainProperty>
          </Properties>
          <ElementMergeDirectives>
            <ElementMergeDirective>
              <Index>
                <DomainClassMoniker Name="Book" />
              </Index>
              <LinkCreationPaths>
                <DomainPath>LibraryHasBooks.Books</DomainPath>
              </LinkCreationPaths>
            </ElementMergeDirective>
            <ElementMergeDirective>
              <Index>
                <DomainClassMoniker Name="CirculationBook" />
              </Index>
              <LinkCreationPaths>
                <DomainPath>LibraryHasCirculationBooks.CirculationBooks</DomainPath>
              </LinkCreationPaths>
            </ElementMergeDirective>
            <ElementMergeDirective>
              <Index>
                <DomainClassMoniker Name="ReferenceBook" />
              </Index>
              <LinkCreationPaths>
                <DomainPath>LibraryHasReferenceBooks.ReferenceBooks</DomainPath>
              </LinkCreationPaths>
            </ElementMergeDirective>
          </ElementMergeDirectives>
        </DomainClass>
        <DomainClass Id="b5e76ed6-5a0e-4b15-a6e4-6694111b288d" Description="Description for ExampleNamespace.Book" Name="Book" DisplayName="Book" InheritanceModifier="Abstract" Namespace="ExampleNamespace" />
        <DomainClass Id="eb9453cf-f7ae-448f-a2ed-64cf06e9b03f" Description="Description for ExampleNamespace.CirculationBook" Name="CirculationBook" DisplayName="Circulation Book" Namespace="ExampleNamespace" HasCustomConstructor="true" GeneratesDoubleDerived="true">
          <BaseClass>
            <DomainClassMoniker Name="Book" />
          </BaseClass>
        </DomainClass>
        <DomainClass Id="451c5461-c9e0-4433-bd6b-9ca772b80d47" Description="Description for ExampleNamespace.ReferenceBook" Name="ReferenceBook" DisplayName="Reference Book" Namespace="ExampleNamespace">
          <BaseClass>
            <DomainClassMoniker Name="Book" />
          </BaseClass>
        </DomainClass>
        <DomainClass Id="34a2607e-c302-4db2-814e-8800bc8554b5" Description="Description for ExampleNamespace.Person" Name="Person" DisplayName="Person" Namespace="ExampleNamespace" />
      </Classes>
      <Relationships>
        <DomainRelationship Id="2d03a799-595d-4207-be7f-27e92ae9c6c2" Description="Description for ExampleNamespace.LibraryHasMembers" Name="LibraryHasMembers" DisplayName="Library Has Members" Namespace="ExampleNamespace" IsEmbedding="true">
          <Properties>
            <DomainProperty Id="e66ad025-9ca3-45a2-ba95-e331e4c3135e" Description="Description for ExampleNamespace.LibraryHasMembers.Amount Owed" Name="AmountOwed" DisplayName="Amount Owed" Kind="Calculated">
              <Type>
                <ExternalTypeMoniker Name="/System/Single" />
              </Type>
            </DomainProperty>
          </Properties>
          <Source>
            <DomainRole Id="2368fd87-4369-4515-86f5-e8ab42f747ed" Description="Description for ExampleNamespace.LibraryHasMembers.Library" Name="Library" DisplayName="Library" PropertyName="Members" PropertyDisplayName="Members">
              <RolePlayer>
                <DomainClassMoniker Name="Library" />
              </RolePlayer>
            </DomainRole>
          </Source>
          <Target>
            <DomainRole Id="51937e41-b8a6-4bc1-a25a-b5bc740cda13" Description="Description for ExampleNamespace.LibraryHasMembers.Member" Name="Member" DisplayName="Member" PropertyName="Library" Multiplicity="ZeroOne" PropagatesDelete="true" PropertyDisplayName="Library">
              <RolePlayer>
                <DomainClassMoniker Name="Person" />
              </RolePlayer>
            </DomainRole>
          </Target>
        </DomainRelationship>
        <DomainRelationship Id="97bd065a-d3e7-4bc3-92b2-2632b4f22513" Description="Description for ExampleNamespace.LibraryHasBooks" Name="LibraryHasBooks" DisplayName="Library Has Books" Namespace="ExampleNamespace" IsEmbedding="true">
          <Source>
            <DomainRole Id="8cb3e691-30e9-4517-bbfa-d62457829047" Description="Description for ExampleNamespace.LibraryHasBooks.Library" Name="Library" DisplayName="Library" PropertyName="Books" PropertyDisplayName="Books">
              <RolePlayer>
                <DomainClassMoniker Name="Library" />
              </RolePlayer>
            </DomainRole>
          </Source>
          <Target>
            <DomainRole Id="eec1832e-89d4-4e89-a883-c78d9f3dacca" Description="Description for ExampleNamespace.LibraryHasBooks.Book" Name="Book" DisplayName="Book" PropertyName="Library" Multiplicity="One" PropagatesDelete="true" PropagatesCopy="true" PropertyDisplayName="Library">
              <RolePlayer>
                <DomainClassMoniker Name="Book" />
              </RolePlayer>
            </DomainRole>
          </Target>
        </DomainRelationship>
        <DomainRelationship Id="7e298837-9aea-4986-91cb-1bd5e047c929" Description="Description for ExampleNamespace.LibraryHasCirculationBooks" Name="LibraryHasCirculationBooks" DisplayName="Library Has Circulation Books" Namespace="ExampleNamespace" IsEmbedding="true">
          <BaseRelationship>
            <DomainRelationshipMoniker Name="LibraryHasBooks" />
          </BaseRelationship>
          <Source>
            <DomainRole Id="80bfb4c1-0f60-4d93-9d1c-c4c05bd7e7db" Description="Description for ExampleNamespace.LibraryHasCirculationBooks.Library" Name="Library" DisplayName="Library" PropertyName="CirculationBooks" PropertyDisplayName="Circulation Books">
              <RolePlayer>
                <DomainClassMoniker Name="Library" />
              </RolePlayer>
            </DomainRole>
          </Source>
          <Target>
            <DomainRole Id="c693072d-e872-4fde-a6f0-8e83179f0ceb" Description="Description for ExampleNamespace.LibraryHasCirculationBooks.CirculationBook" Name="CirculationBook" DisplayName="Circulation Book" PropertyName="Library" Multiplicity="One" PropagatesDelete="true" PropagatesCopy="true" PropertyDisplayName="Library">
              <RolePlayer>
                <DomainClassMoniker Name="CirculationBook" />
              </RolePlayer>
            </DomainRole>
          </Target>
        </DomainRelationship>
        <DomainRelationship Id="2cb6e0f4-8f33-4349-8075-2628a9521e16" Description="Description for ExampleNamespace.LibraryHasReferenceBooks" Name="LibraryHasReferenceBooks" DisplayName="Library Has Reference Books" Namespace="ExampleNamespace" IsEmbedding="true">
          <BaseRelationship>
            <DomainRelationshipMoniker Name="LibraryHasBooks" />
          </BaseRelationship>
          <Source>
            <DomainRole Id="71475276-1a94-48ed-aca3-4a37a5e06645" Description="Description for ExampleNamespace.LibraryHasReferenceBooks.Library" Name="Library" DisplayName="Library" PropertyName="ReferenceBooks" PropertyDisplayName="Reference Books">
              <RolePlayer>
                <DomainClassMoniker Name="Library" />
              </RolePlayer>
            </DomainRole>
          </Source>
          <Target>
            <DomainRole Id="e5ce0a75-6b17-4b21-aa85-f4315e43088a" Description="Description for ExampleNamespace.LibraryHasReferenceBooks.ReferenceBook" Name="ReferenceBook" DisplayName="Reference Book" PropertyName="Library" Multiplicity="One" PropagatesDelete="true" PropagatesCopy="true" PropertyDisplayName="Library">
              <RolePlayer>
                <DomainClassMoniker Name="ReferenceBook" />
              </RolePlayer>
            </DomainRole>
          </Target>
        </DomainRelationship>
        <DomainRelationship Id="c3ad950d-5db8-4362-bc71-4fd2e494a65e" Description="Description for ExampleNamespace.PersonChecksOutCirculationBooks" Name="PersonChecksOutCirculationBooks" DisplayName="Person Checks Out Circulation Books" Namespace="ExampleNamespace">
          <Properties>
            <DomainProperty Id="ed46a26c-f6f4-4402-b814-4e26f73d2a15" Description="Description for ExampleNamespace.PersonChecksOutCirculationBooks.Due Date" Name="DueDate" DisplayName="Due Date" Kind="CustomStorage">
              <Type>
                <ExternalTypeMoniker Name="/System/DateTime" />
              </Type>
            </DomainProperty>
          </Properties>
          <Source>
            <DomainRole Id="8860946b-d755-47c6-82ed-26600c08b6bb" Description="Description for ExampleNamespace.PersonChecksOutCirculationBooks.Person" Name="Person" DisplayName="Person" PropertyName="CirculationBooks" PropertyDisplayName="Circulation Books">
              <RolePlayer>
                <DomainClassMoniker Name="Person" />
              </RolePlayer>
            </DomainRole>
          </Source>
          <Target>
            <DomainRole Id="f7afeca0-9165-44fc-93c8-167160b26ae3" Description="Description for ExampleNamespace.PersonChecksOutCirculationBooks.CirculationBook" Name="CirculationBook" DisplayName="Circulation Book" PropertyName="Person" Multiplicity="ZeroOne" PropertyDisplayName="Person">
              <RolePlayer>
                <DomainClassMoniker Name="CirculationBook" />
              </RolePlayer>
            </DomainRole>
          </Target>
        </DomainRelationship>
      </Relationships>
      <Types>
        <ExternalType Name="DateTime" Namespace="System" />
        <ExternalType Name="String" Namespace="System" />
        <ExternalType Name="Int16" Namespace="System" />
        <ExternalType Name="Int32" Namespace="System" />
        <ExternalType Name="Int64" Namespace="System" />
        <ExternalType Name="UInt16" Namespace="System" />
        <ExternalType Name="UInt32" Namespace="System" />
        <ExternalType Name="UInt64" Namespace="System" />
        <ExternalType Name="SByte" Namespace="System" />
        <ExternalType Name="Byte" Namespace="System" />
        <ExternalType Name="Double" Namespace="System" />
        <ExternalType Name="Single" Namespace="System" />
        <ExternalType Name="Guid" Namespace="System" />
        <ExternalType Name="Boolean" Namespace="System" />
        <ExternalType Name="Char" Namespace="System" />
      </Types>
      <XmlSerializationBehavior Name="ExampleModelSerializationBehavior" Namespace="ExampleNamespace">
        <ClassData>
          <XmlClassData TypeName="Library" MonikerAttributeName="" MonikerElementName="libraryMoniker" ElementName="library" MonikerTypeName="LibraryMoniker">
            <DomainClassMoniker Name="Library" />
            <ElementData>
              <XmlPropertyData XmlName="name" IsMonikerKey="true">
                <DomainPropertyMoniker Name="Library/Name" />
              </XmlPropertyData>
              <XmlRelationshipData UseFullForm="true" RoleElementName="members">
                <DomainRelationshipMoniker Name="LibraryHasMembers" />
              </XmlRelationshipData>
              <XmlRelationshipData RoleElementName="books">
                <DomainRelationshipMoniker Name="LibraryHasBooks" />
              </XmlRelationshipData>
              <XmlRelationshipData UseFullForm="true" RoleElementName="circulationBooks">
                <DomainRelationshipMoniker Name="LibraryHasCirculationBooks" />
              </XmlRelationshipData>
              <XmlRelationshipData UseFullForm="true" RoleElementName="referenceBooks">
                <DomainRelationshipMoniker Name="LibraryHasReferenceBooks" />
              </XmlRelationshipData>
            </ElementData>
          </XmlClassData>
          <XmlClassData TypeName="Book" MonikerAttributeName="" MonikerElementName="bookMoniker" ElementName="book" MonikerTypeName="BookMoniker">
            <DomainClassMoniker Name="Book" />
          </XmlClassData>
          <XmlClassData TypeName="CirculationBook" MonikerAttributeName="" SerializeId="true" MonikerElementName="circulationBookMoniker" ElementName="circulationBook" MonikerTypeName="CirculationBookMoniker">
            <DomainClassMoniker Name="CirculationBook" />
          </XmlClassData>
          <XmlClassData TypeName="ReferenceBook" MonikerAttributeName="" MonikerElementName="referenceBookMoniker" ElementName="referenceBook" MonikerTypeName="ReferenceBookMoniker">
            <DomainClassMoniker Name="ReferenceBook" />
          </XmlClassData>
          <XmlClassData TypeName="Person" MonikerAttributeName="" SerializeId="true" MonikerElementName="personMoniker" ElementName="person" MonikerTypeName="PersonMoniker">
            <DomainClassMoniker Name="Person" />
            <ElementData>
              <XmlRelationshipData UseFullForm="true" RoleElementName="circulationBooks">
                <DomainRelationshipMoniker Name="PersonChecksOutCirculationBooks" />
              </XmlRelationshipData>
            </ElementData>
          </XmlClassData>
          <XmlClassData TypeName="LibraryHasMembers" MonikerAttributeName="" MonikerElementName="libraryHasMembersMoniker" ElementName="libraryHasMembers" MonikerTypeName="LibraryHasMembersMoniker">
            <DomainRelationshipMoniker Name="LibraryHasMembers" />
            <ElementData>
              <XmlPropertyData XmlName="amountOwed" Representation="Ignore">
                <DomainPropertyMoniker Name="LibraryHasMembers/AmountOwed" />
              </XmlPropertyData>
            </ElementData>
          </XmlClassData>
          <XmlClassData TypeName="LibraryHasBooks" MonikerAttributeName="" MonikerElementName="libraryHasBooksMoniker" ElementName="libraryHasBooks" MonikerTypeName="LibraryHasBooksMoniker">
            <DomainRelationshipMoniker Name="LibraryHasBooks" />
          </XmlClassData>
          <XmlClassData TypeName="LibraryHasCirculationBooks" MonikerAttributeName="" MonikerElementName="libraryHasCirculationBooksMoniker" ElementName="libraryHasCirculationBooks" MonikerTypeName="LibraryHasCirculationBooksMoniker">
            <DomainRelationshipMoniker Name="LibraryHasCirculationBooks" />
          </XmlClassData>
          <XmlClassData TypeName="LibraryHasReferenceBooks" MonikerAttributeName="" MonikerElementName="libraryHasReferenceBooksMoniker" ElementName="libraryHasReferenceBooks" MonikerTypeName="LibraryHasReferenceBooksMoniker">
            <DomainRelationshipMoniker Name="LibraryHasReferenceBooks" />
          </XmlClassData>
          <XmlClassData TypeName="PersonChecksOutCirculationBooks" MonikerAttributeName="" MonikerElementName="personChecksOutCirculationBooksMoniker" ElementName="personChecksOutCirculationBooks" MonikerTypeName="PersonChecksOutCirculationBooksMoniker">
            <DomainRelationshipMoniker Name="PersonChecksOutCirculationBooks" />
            <ElementData>
              <XmlPropertyData XmlName="dueDate">
                <DomainPropertyMoniker Name="PersonChecksOutCirculationBooks/DueDate" />
              </XmlPropertyData>
            </ElementData>
          </XmlClassData>
          <XmlClassData TypeName="LibraryDiagram" MonikerAttributeName="" MonikerElementName="minimalLanguageDiagramMoniker" ElementName="minimalLanguageDiagram" MonikerTypeName="LibraryDiagramMoniker">
            <DiagramMoniker Name="LibraryDiagram" />
          </XmlClassData>
        </ClassData>
      </XmlSerializationBehavior>
      <ExplorerBehavior Name="LibraryExplorer" />
      <ConnectionBuilders>
        <ConnectionBuilder Name="PersonChecksOutCirculationBooksBuilder">
          <LinkConnectDirective>
            <DomainRelationshipMoniker Name="PersonChecksOutCirculationBooks" />
            <SourceDirectives>
              <RolePlayerConnectDirective>
                <AcceptingClass>
                  <DomainClassMoniker Name="Person" />
                </AcceptingClass>
              </RolePlayerConnectDirective>
            </SourceDirectives>
            <TargetDirectives>
              <RolePlayerConnectDirective>
                <AcceptingClass>
                  <DomainClassMoniker Name="CirculationBook" />
                </AcceptingClass>
              </RolePlayerConnectDirective>
            </TargetDirectives>
          </LinkConnectDirective>
        </ConnectionBuilder>
      </ConnectionBuilders>
      <Diagram Id="2b61d4f9-d7e8-4aa6-a889-d553a28eddfc" Description="Description for ExampleNamespace.LibraryDiagram" Name="LibraryDiagram" DisplayName="Minimal Language Diagram" Namespace="ExampleNamespace">
        <Class>
          <DomainClassMoniker Name="Library" />
        </Class>
      </Diagram>
      <Designer FileExtension="ex1" EditorGuid="a642b50b-9479-41b0-9268-69cf1d5871b0">
        <RootClass>
          <DomainClassMoniker Name="Library" />
        </RootClass>
        <XmlSerializationDefinition CustomPostLoad="false">
          <XmlSerializationBehaviorMoniker Name="ExampleModelSerializationBehavior" />
        </XmlSerializationDefinition>
        <Validation UsesMenu="false" UsesOpen="false" UsesSave="false" UsesLoad="false" />
        <DiagramMoniker Name="LibraryDiagram" />
      </Designer>
      <Explorer ExplorerGuid="0eff263d-2177-4ad7-b632-d65da83e39cf" Title="experiment1 Explorer">
        <ExplorerBehaviorMoniker Name="ExampleModel/LibraryExplorer" />
      </Explorer>
    </Dsl>
    

Generating Code from the Domain-Specific Language

To generate an API from a domain-specific language

  1. On the Project menu, click GenFromModel Properties.

  2. In Default namespace, type ExampleNamespace.

  3. Save and close the project properties.

  4. In Solution Explorer, expand Properties, and double-click AssemblyInfo.cs to open it.

  5. At the bottom of this file, insert the following assembly instruction:

    [assembly: System.CLSCompliant(true)]
    
  6. In Solution Explorer, click GenFromModel to highlight it.

  7. Add a text file, DomainModel.tt, to the project, and insert the following text into it:

    <#@ include file="Dsl\DomainModelCodeGenerator.tt" #>
    <#@ Dsl processor="DslDirectiveProcessor"  requires="fileName='library.dsl'" #>
    

    Note

    When you generate a template, a dialog box opens and warns you not to run text templates from untrusted sources. If you do not want to see this message again, select the Do not show this message again check box, and click OK. Otherwise, click OK.

  8. Add a text file, DomainClasses.tt, to the project, and insert the following text into it:

    <#@ include file="Dsl\DomainClassCodeGenerator.tt" #>
    <#@ Dsl processor="DslDirectiveProcessor"  requires="fileName='library.dsl'" #>
    
  9. Add a text file, DomainRelationships.tt, to the project, and insert the following text into it:

    <#@ include file="Dsl\DomainRelationshipCodeGenerator.tt" #>
    <#@ Dsl processor="DslDirectiveProcessor"  requires="fileName='library.dsl'" #>
    
  10. Add a text file, Diagram.tt, to the project, and insert the following text into it:

    <#@ Dsl processor="DslDirectiveProcessor" requires="fileName='library.dsl'" #>
    <#@ include file="Dsl\Diagram.tt" #>
    
  11. Add a text file, ToolboxHelper.tt, to the project, and insert the following text into it:

    <#@ Dsl processor="DslDirectiveProcessor" requires="fileName='library.dsl'" #>
    <#@ include file="Dsl\ToolboxHelper.tt" #>
    
  12. Add a code file, StubMethods.cs, to the project, and insert the following text into it:

    using DslModeling = global::Microsoft.VisualStudio.Modeling;
    
    namespace ExampleNamespace
    {
        public partial class CirculationBook : CirculationBookBase
        {
            #region Constructors
            /// <summary>
            /// Constructor
            /// </summary>
            /// <param name="store">Store where new element is to be created.</param>
            /// <param name="propertyAssignments">List of domain property id/value pairs to set once the element is created.</param>
            public CirculationBook(DslModeling::Store store, params DslModeling::PropertyAssignment[] propertyAssignments)
                : this(store != null ? store.DefaultPartition : null, propertyAssignments)
            {
            }
    
            /// <summary>
            /// Constructor
            /// </summary>
            /// <param name="partition">Partition where new element is to be created.</param>
            /// <param name="propertyAssignments">List of domain property id/value pairs to set once the element is created.</param>
            public CirculationBook(DslModeling::Partition partition, params DslModeling::PropertyAssignment[] propertyAssignments)
                : base(partition, propertyAssignments)
            {
            }
            #endregion
        }
    
        public partial class LibraryHasMembers : DslModeling::ElementLink
        {
            internal float GetAmountOwedValue()
            {
                throw new System.Exception("The method or operation is not implemented.");
            }
        }
    
        public partial class PersonChecksOutCirculationBooks : DslModeling::ElementLink
        {
            internal void SetDueDateValue(System.DateTime newValue)
            {
                throw new System.Exception("The method or operation is not implemented.");
            }
    
            internal System.DateTime GetDueDateValue()
            {
                throw new System.Exception("The method or operation is not implemented.");
            }
        }
    }
    
  13. On the File menu, click Save All.

    The text templates generate .cs files for the generated API.

  14. In Class View, expand the ExampleNamespace node.

    The classes that were generated appear.

See Also

Concepts

Functionality of the Generated API

Reference

DefaultPartition

PropertyAssignment

ElementLink

Other Resources

Domain-Specific Language Tools Glossary

Change History

Date

History

Reason

July 2008

Rewrote and refactored project.

Content bug fix.