Using the Domain-specific Language
Now that we have completed our domain model and designer definition we are ready to use the language for the first time. To do this we can simply choose "Start debugging" (press F5) from within Visual Studio Team System, which results in a new, so-called "experimental" environment of Visual Studio were we can use our language. We will create a new model based on the domain-specific language template; in our case this is the Service Description
template. We'll add a new empty model based on this template to the Visual Studio project to prepare for graphically modeling the service contract for any service we would like.
Modeling a Service
shows the concepts available for modeling the service contract. You might notice the absence of the DataContract and MessageHeader concepts. These concepts are represented as compartment shapes "inside" the MessageShape. Therefore we cannot create them stand-alone from a message and so there's no need for these concepts to appear in the toolbox.
|Figure 6. New Toolbox Items: The figure shows available Toolbox items for the sample DSL.||
|Figure 7. Message Modeling: Here's what the process of visually modeling a message with DataContracts looks like.||
illustrates that we can simply right-click on the DataContract placeholder in the MessageShape to add a DataContract to it. The same is true for adding a MessageHeader. This is all default behavior of the DSL Tools designer that we created for our language.
|Figure 8. Model Service: Here's a RestaurantService modeled with the sample DSL.|
After playing around a little with our Domain-specific Language we modelled the service contract for a sample "RestaurantService." As you can see in Figure 8
the service has one ServiceInterface named RestaurantServiceInterface
that exposes three ServiceOperations named GetRestaurants
. When we have a look at the GetRestaurants service operation we can see that it has an incoming message named GetRestaurants
and an outgoing message named GetRestaurantResponse
. At this point you can also see where we needed the two extra ShapeIcons
that we described earlier. What we didn't show then is that we added a MessageType
property to our Message concept. MessageType is an enumeration with InboundMessage
as possible values. Based on the value of this property on the Message level we decide which icon to show in the MessageShape. The icons are specified in the ShapeIcon elements in the designer definition mentioned earlier.
|Figure 9. Custom UI Property Editor: Attaching an XSD to a Message.|
As you can see in Figure 8
, all service operations have one or more DataContracts specified. We already demonstrated that you can simply right-click a MessageShape to manually add a DataContract to the message. Adding a DataContract in this way is out-of-the-box functionality that you get when creating embedding relations between concepts. However we decided to make the DSL a little more user-friendly and therefore built some additional functionality by using a piece of custom code. The default way to set a value of a property on a domain concept in the Domain-specific Language designer is to simply type the value of the property in the Visual Studio property grid. We didn't like that too much, especially for the SchemaLocation
property on our message concept. Therefore, we created a custom UiTypeEditor coupled with the SchemaLocation
property of the message shape in our language. Figure 9
demonstrates that we now have the little ellipsis button (
) that appears in the Visual Studio property grid for the SchemaLocation
When we click the button a file dialog box pops up (see Figure 10
) that enables us to navigate to the XSD file that contains the parts of our message. In our example we select the RestaurantMessages.xsd
|Figure 10. Selecting an XSD: Here's how you select the message XSD file.||
|Figure 11: Custom Menu Item: Here's how the custom menu item for the MessageShape looks.||
With the XML schema that contains a description of our messages selected, now we must select the actual message in the XSD file. To support this we created an extra menu item that is only available when right-clicking on a MessageShape. Figure 11
shows how we use this custom "Select message from XSD" menu item on the MessageShape to select a message from the XSD.
When we select this menu item another window pops up that provides us with a nice overview of all the messages that are described in the selected XSD file. Figure 12
shows that the RestaurantMessages.xsd
file we selected earlier describes four messages. We can now select a message and see the DataContracts referenced in that message. Please note that the DataContracts itself are not defined in the RestaurantMessages.xsd file but only referenced from another XSD file.
|Figure 12: Selecting a Message Element: From this window, you can select among messages defined in the XSD file.||
|Figure 13: Message Shape: Here's a properly-populated message shape.||
After selecting the rateRestaurant
message in the "Select message" window the MessageShape in the model gets nicely populated with the correct name of the message, DataContracts, and all the appropriate references and type information of the message and DataContracts. All of the above functionality is added by using custom code. The DSL Tools API makes it relatively easy to add features you implemented in any .NET technology you find appropriate to extend the DSL's feature set.
Now that we've finished modeling our service contract using the modeling technique described above we can generate the artifact. In the domain-specific language we are describing in this article we want to generate a WS-I BP 1.1-compliant WSDL file that represents the service contract description. The out-of-the-box technique that comes with the DSL Tools for generating artifacts is T4 text templates. T4 text templates have a CodeSmith
-like syntax and are processed by a text transformation engine that is part of the DSL Tools. This is the same engine used for the Guidance Automation Toolkit. Basically it comes down to mixing boilerplate text with information that comes from models you create in the language. For our domain-specific language we choose not to use the T4 templates and instead generated our artifacts in plain C# code. We simply added custom code that uses the model information to communicate with our code to generate WSDL. This again demonstrates the customizations possibilities of the DSL Tools API.
We described a sample and prototype domain-specific language that we created for generating service contract descriptions and how they fit into Microsoft's vision and idea of Software Factories. The language is capable of generating WSDL based on the model we created in the language designer. At this moment the language only focuses on the WSDL part of the service contract and it heavily relies on XSD for describing the messages and data contracts. One feature that we didn't describe in this article is the possibility to read an existing WSDL file and create a graphical representation of the service contract in the language designer.
Due to the very early beta-like state of the DSL Tools we didn't go into too much detail about the actual building of a domain-specific language. We primarily wanted to demonstrate the power of domain-specific languages in general and provide you with an example that can you could build in the current release of the DSL Tools. In this respect it is important to note that the first release of the DSL Tools might miss a few of your requirements. Don't let this fact discourage you from starting to build domain-specific languages. We demonstrated that you can address these potential missing features by writing some custom code.
We will make this domain-specific language for modeling service contracts available for download as soon as Microsoft releases the DSL Tools. At that point we will also provide some more technical details about the features we implemented in this language. We'll also post more details and the download in our blogs.