Using DSL Integration Service (DIS) – Part 2

In the last post I’ve introduced the DSL Integration Service and it’s own usage scenarios. Now I will get into the code, illustrating the implementation of one specific scenario:

Suppose you already have a DSL which enables the specification of business entities. Now Suppose that you need to implement a DSL for the user interface specification. It would be nice to have the possibility to reference the entities defined using the entities DSL, when specifying the user interface with the second DSL.

To do so I’ve implemented a new Visual Studio 2005 tool window that displays all the business entities and corresponding attributes in all available models. Then selecting one user interface model I’m be able to create my user interface specification by doing drag & drop of the available business entities into the UI model.

These are the steps you need to follow to implement something similar:

First you need to mark the entities DSL as exportable. You do so by editing the Package.tt in DslPackage project:

[Microsoft.VisualStudio.Modeling.Integration.RegisterAsExportable(

typeof(<#= directiveName #>DomainModel),

typeof(<#= directiveName #>SerializationBehaviorMonikerResolver),

typeof(<#=domainModelRoot#>),

typeof(<#= directiveName #>SerializationBehavior))]

internal sealed partial class <#= dslName #>Package : <#= dslName #>PackageBase

{

}And for the target DSL that’s all. You need only to garantee that , in the DSL definition, you do not have any element with the attribute “Generates Double Derived” with a “True” value assigned because if you don’t the integration service will generate an error. This limitation as already been assumed in the DSL forum.

To implement a Visual Studio 2005 tool window you need to create a new Visual Studio Integration Package

In the VSIP you need to get the reference to the Integration Service. With the service reference you can get an instance of the business entities domain model browser. With the domain model browser you can get a reference to all exported instances of a given model element. Finally you expose the elements data by geting a reference to each exported instance:

IDslIntegrationService service = Business_Entities_Selector.GetGlobalService(typeof(IDslIntegrationService)) as IDslIntegrationService;

IDomainModelBrowser domainModelBrowser = service.GetDomainModelBrowser(“Company.Models.Entities”);

ReadOnlyCollection<ExportedInstance> exportedInstances = domainModelBrowser.FindAllInstances(domainModelBrowser.GetExportedClassByNamespace(“Company.Models.Entities\BusinessEntity”));

BusinessEntity resolvedElement = (BusinessEntity)service.ResolveExportedInstanceInDocument(“Company.Models.Entities”, “mell://” + exportedInstance.Namespace, true);

Still in the VSIP project you need to enable the Drag & Drop operation. You do so by calling the DoDragDrop method in the ItemDrag event from the TreeView control:

private void TreeView1_ItemDrag(object sender, ItemDragEventArgs e)

{

DoDragDrop(e.Item, DragDropEffects.Copy);

}

In the User Interface DSL you need to first enable the drag & drop operations in corresponding model:

protected override void OnAssociated(DiagramAssociationEventArgs e)

{

base.OnAssociated(e);

// Ensure we have a view

if (e.DiagramView == null || e.DiagramView.DiagramClientView == null)

return;

// Wireup the drag/drop support

Control ctrl = e.DiagramView.DiagramClientView;

ctrl.AllowDrop = true;

ctrl.DragOver += new DragEventHandler(OnDragOver);

ctrl.DragDrop += new DragEventHandler(OnDragDrop);

}

Then implement the OnDragOver event:

private void OnDragOver(object sender, DragEventArgs e)

{

e.Effect = DragDropEffects.Copy;

}

And finally the OnDragDrop event. The model element creation it’s done here:

private void OnDragDrop(object sender, DragEventArgs e)

{

if (e.Data.GetDataPresent(typeof(TreeNode)))

{

using (Transaction transaction = this.Store.TransactionManager.BeginTransaction())

{

ExampleElement exampleElement = (ExampleElement)this.Store.ElementFactory.CreateElement(ExampleElement.DomainClassId);

TreeNode entityNode = (TreeNode)e.Data.GetData(typeof(TreeNode));

exampleElement.Name = entityNode.Text;

foreach (TreeNode node in entityNode.Nodes)

{

Attribute attribute = (Attribute)this.Store.ElementFactory.CreateElement(Attribute.DomainClassId);

attribute.Name = node.Text;

exampleElement.attributes.Add(attribute);

}

ExampleModel exampleModel = GetModel(this.Store);

exampleModel.Elements.Add(exampleElement);

transaction.Commit();

}

}

}

You need to implement all this in a partial class of the UserInterfaceDiagram class

And that’s it. You now can start building you user interface specification by using the entities definitions made in another DSL.

Advertisements

One thought on “Using DSL Integration Service (DIS) – Part 2

  1. Piyush says:

    Thanks for this detailed article on this not-so-documented feature. Do you know how can I access DSLs in pre-compiled assembly from my project?

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: