Pablo Galiano :

Subscriptions

<March 2010>
SuMoTuWeThFrSa
28123456
78910111213
14151617181920
21222324252627
28293031123
45678910

News

Subscribe to Pablo Galiano by Email

Post Categories

DSL (RSS)

DSL VS10 / Locking policies

***Disclaimer: This information applies to Visual Studio 2010 Beta 1 only.***

 

Another new feature of the new version of the DSL toolkit is the ability to locks certain operations in a DSL. The idea is that we can define locking policies for a DSL and those policies are executed at runtime to constraint specific operations such as Add/Delete/Update etc.

These locking policies can be defined at three different levels , Store, Partition and ModelElement respectively.

Defining our own locking policies

It is really simple to create our own policy class, we just need to create a class that inherits from ILockingPolicy.

Then we need to define the locks that we are going to return, and for that we have three levels of granularity:

  • Store
  • Partition
  • ModelElement

Locks are transitive following the “Store –> Partition –> ModelElement” object hierarchy.

That means that if we set locks at the Store level, those locks also apply to the Partition and the ModelElement levels.

The lock types are:

image

 

public class MyLockingPolicy : ILockingPolicy
{
    public Locks RefineLocks(ModelElement element, Locks proposedLocks)
    {
        return proposedLocks;
    }

    public Locks RefineLocks(Partition partition, Locks proposedLocks)
    {
        return proposedLocks;
    }

    public Locks RefineLocks(Store store, Locks proposedLocks)
    {
        // TODO: return corresponding locks and they will also apply to Partition and ModelElement
    }

}

 

Injecting our own ILockingPolicy

The Store class constructor sets the locking policy by querying for a ILockingPolicy service. That means that one possible way to inject our own locking policy is to override the GetService method and return our policy class:

internal partial class MyDocData
{
    private ILockingPolicy myLockingPolicy;

    public override object GetService(Type serviceType)
    {
        if (serviceType == typeof(SLockingPolicy) || serviceType == typeof(ILockingPolicy))
        {
            if (myLockingPolicy == null)
            {
                myLockingPolicy = new MyLockingPolicy();
            }

            return myLockingPolicy;
        }

        return base.GetService(serviceType);
    }
}

 

At runtime the DSL infrastructure will query for existing locks using a set of extension methods located in the new ImmutabilityExtensionMethods class and constraint or not an operation accordingly.

 

The hardware model sample

I published a sample that shows how to lock a DSL.

The scenario is that there are two personas:

  • Developer: He uses the VS full IDE to author a hardware model.
  • Architect: He uses an Isolated shell to review the model and cannot do any modifications to it.

The locks are being set by detecting the shell SKU.

 

Pablo

posted Thursday, July 16, 2009 5:32 AM by pga with 0 Comments

DSL / VS 10 ModelBus part 2

***Disclaimer: This information applies to Visual Studio 2010 Beta 1 only.***

 

In the first part of this series I described general concepts around the ModelBus infrastructure. In this second part I will describe the model bus service and how MEF is involved.

The ModelBus as a Service

The Microsoft.VisualStudio.Modeling.Sdk.Integration.Shell.10.0 is a VS Package that defines one core service, the IModelBus service.

The model bus service creates and uses its own MEF composition container with two directory catalogs pointing to:

  • %LocalAppData%\Microsoft\VisualStudio\10.0\Extensions
  • %VS10_Install_Dir%\Extensions

 

A DSL exports an adapter manager and provides some metadata to specify which adapter this manager manages:

[Export(typeof(ModelBusAdapterManager))]

[HandlesAdapter(“MyAdapterId”)]
public partial class MyAdapterManager : VsModelingAdapterManager
{


}

 

The main responsibility of the model bus is to find registered adapter managers, for that the composition container is used:

container.GetExportedObjects<ModelBusAdapterManager>()

 

In order to register a DSL with the model bus we need to do the following steps:

  • Update the model definition to introduce a domain property that will hold the model reference
  • Update the model serialization behavior to include the model reference serialization
  • Create an adapter for the DSL
  • Create an export an adapter manager for the DSL
  • Deploy the DSL under extensions (done automatically at compilation time via the VS SDK msbuild target)

 

Stay tuned,

Pablo

posted Tuesday, July 14, 2009 5:53 AM by pga with 0 Comments

DSL / VS 10 ModelBus part 1

***Disclaimer: This information applies to Visual Studio 2010 Beta 1 only.***

 

One of the new main features of the new version of the DSL toolkit is the “ModelBus”. The model bus basically allows a model element to reference another model element (ModelBusReference). These two model elements could be defined either in the same DSL or in different ones. With a ModelBusReference we can do interesting model interactions such as navigating the references back and forth, performing validation across models, etc.

 

The ModelBus infrastructure lives in two core assemblies:

  • Microsoft.VisualStudio.Modeling.Sdk.Integration.10.0
  • Microsoft.VisualStudio.Modeling.Sdk.Integration.Shell.10.0

 

Microsoft.VisualStudio.Modeling.Sdk.Integration.10.0

As the name implies, this assembly contains concepts that are totally decoupled from Visual Studio.

The main generic concepts are:

ModeBusAdapter

Is a bridge between the model bus and the underlying model. Therefore each model has its own adapter.

It’s main responsibilities are:

  • Get all references of an element type
  • Resolve a reference into an object
  • Get the view associated with the model

ModelBusAdapterManager

Is used to create and control the lifetime of adapters.

It’s main responsibilities are:

  • Create adapters
  • Create reference to a model
  • Return the list of supported adapters
  • Return the list of exposed element types. An exposed element type is an element that can be referenced by another element

ModelBusReference

Encapsulates information about a reference in the model bus. It is composed of:

  • Adapter reference
  • Adapter id
  • Model display name
  • Element display name

It is being serialized as:

image

ModelBusAdapterReference

Represents the base class for adapter references

ModelBusView

Allows a client to manipulate the design surface of the model (if applicable)

It’s main responsibilities are:

  • Open view
  • Close view
  • Show view
  • Hide view
  • Select UI elements

 

Then we have a set of derived classes that are specific to DSLs:

  • ModeBusAdapter<- ModelingAdapter
  • ModelBusAdapterReference <- ModelingAdapterReference

ModelingAdapter

Represents the base class for DSL based adapters. In this case the model is a DSL model.

ModelingAdapterReference

Encapsulates information about a model element reference, it is composed of:

  • Model element id
  • View id
  • Model file absolute path

It is being serialized as:

image

 

Microsoft.VisualStudio.Modeling.Sdk.Integration.Shell.10.0

In this assembly there are concepts that are coupled to the Visual Studio infrastructure.

VsModelingAdapterManager

This adapter manager introduces the notion of document handlers that knows how to handle a DocData concept.

VsModelingView

This implementation is tied to the DocView concept.

 

Stay tuned,

Pablo

posted Tuesday, July 14, 2009 4:33 AM by pga with 7832 Comments

DSL / VS 10 The Store Viewer

***Disclaimer: This information applies to Visual Studio 2010 Beta 1 only.***

 

There is a really useful utility in the new version of DSL, that is the Store Viewer.

The API to use it is really simple:

 

using Microsoft.VisualStudio.Modeling.Diagnostics;

StoreViewer.Show(store);

 

 image

With this viewer already implemented, the next logic step for me is to have a VS debugger visualizer. We should cross the fingers and maybe in the next Beta 2 we will see it.

 

Pablo

posted Monday, July 13, 2009 6:58 AM by pga with 0 Comments

How do I create a ModelElement via API

My eighteenth How do I is up.

Scenario

Let's say that we start from the Minimal Language DSL template and we have an ExampleElement domain class that has a Name domain property with the Is Element Name flag set to true.

Because it has the IsElementName flag, every time that we create a ExampleElement with the UI (toolbox or model explorer) the element is created with a default name. This default name is composed of the type name of the concept plus an index. Example : ElementName1, ElementName2, etc.

The focus of this How do I shows how to create the model element programmatically.

 

Interfaces and classes needed

 

Code snippet

Wrong way:

private void CreateElement(Store store)

{

    using(Transaction tx = store.TransactionManager.BeginTransaction("Add ExampleElement"))

    {

        ExampleModel root = store.ElementDirectory.FindElements<ExampleModel>().First() as ExampleModel;

 

        ExampleElement element =

            this.Store.ElementFactory.CreateElement(ExampleElement.DomainClassId) as ExampleElement;

 

        root.Elements.Add(element);

 

        tx.Commit();

    }

}

 

Right way:

 

private void CreateElement(Store store)

{

    using(Transaction tx = store.TransactionManager.BeginTransaction("Add ExampleElement"))

    {

        ExampleModel root = store.ElementDirectory.FindElements<ExampleModel>().First() as ExampleModel;

 

        ExampleElement element =

            store.ElementFactory.CreateElement(ExampleElement.DomainClassId) as ExampleElement;

 

        ElementOperations elementOperations =

            new ElementOperations(store as IServiceProvider, store);

 

        ElementGroup elementGroup = new ElementGroup(store);

        elementGroup.Add(element);

        elementGroup.MarkAsRoot(element);

        elementOperations.MergeElementGroup(root, elementGroup);

 

        tx.Commit();

    }

}

 

 

Assemblies needed

  • Microsoft.VisualStudio.Shell.Interop
  • Microsoft.VisualStudio.Modeling.Sdk.Shell
  • Microsoft.VisualStudio.Modeling.Sdk.Diagrams

 

Stay tuned,

Pablo

posted Tuesday, September 30, 2008 8:17 AM by pga with 1 Comments

VSXDevCon08 pictures

Here are some pictures for the VSX Developer Conference with me in the front. :)

The videos are going to posted at MSDN soon...

 con08_1.png

con08_2.png

Pablo

posted Monday, September 22, 2008 2:33 PM by pga with 3 Comments

T4 Editor RTM is OUT!!!

As Victor announced it, after great efforts the T4 Editor v1.0 was finally out.

I don't need to tell you how much the user experience can drastically change when you use it, having syntax coloring, intellisense, code generation preview, support for multiple T4 hosts, etc etc.

Check it out here

Pablo

posted Monday, September 15, 2008 11:39 AM by pga with 1 Comments

How do I cancel a model element property value editing operation

My fourteenth How do I is up.

Scenario

Let's say that we want to cancel an editing operation in a model element property if the new value meets a certain condition. The focus of this How do I tackles this scenario.

In the next sample we have a MyLanguage dsl and a MyElement domain class and we want to cancel the editing operation over the "Foo" property if the new value is empty.

 

Interfaces and classes needed

 

Code snippet

    public partial class MyLanguageDomainModel

    {

        protected override Type[] GetCustomDomainModelTypes()

        {

            var types = new List<Type>();

 

            types.AddRange(base.GetCustomDomainModelTypes());

            types.Add(typeof(MyElementChangeRule));

 

            return types.ToArray();

        }

    }

 

    [RuleOn(typeof(MyElement), FireTime = TimeToFire.TopLevelCommit)]

    public partial class MyElementChangeRule : ChangeRule

    {

        public override void ElementPropertyChanged(ElementPropertyChangedEventArgs e)

        {

            if(!e.ModelElement.Store.TransactionManager.CurrentTransaction.IsSerializing)

            {

                if(e.DomainProperty.Name.Equals("Foo"))

                {

                    if(string.IsNullOrEmpty(e.NewValue.ToString()))

                    {

                        //The name cannot be empty, therefore we cancel the change

                        PackageUtility.ShowError(e.ModelElement.Store, "Value cannot be empty");

                        e.ModelElement.Store.TransactionManager.CurrentTransaction.Rollback();

                    }

                }

            }

        }

    }

Assemblies needed

  • Microsoft.VisualStudio.Modeling.Sdk, Version=9.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a

 

Stay tuned,

Pablo

posted Thursday, August 28, 2008 5:49 PM by pga with 1 Comments

How do I know when a model element is being added by a user demand

My ninth How do I is up.

Scenario

Let's say that we have some "Add rules" in our model to perform some custom operation every time a model element is added. One common problem is that we want to perform this operation only when the user creates a model element on demand, this can be translated to the user drags a shape from the toolbox, uses the model explorer, etc. But the add rule is also fired when the store is being deserialized and somehow we need to distinguish both cases. The focus of this How do I tackles this scenario.

 

Interfaces and classes needed

 

Code snippet

    var transaction = e.ModelElement.Store.TransactionManager.CurrentTransaction;

 

    if(transaction != null && !transaction.IsSerializing)

    {

//TODO: perform operation 

    }

 

Assemblies needed

  • Microsoft.VisualStudio.Modeling.Sdk

 

Stay tuned,

Pablo

posted Monday, August 25, 2008 6:32 AM by pga with 1 Comments

How do I get the model element associated to a shape and vice versa

My sixth How do I is up.

Scenario

The scenario here is really simple, we want to get the shape associated with a model element or vice versa. The focus of this How do I tackles this scenario.

 

Interfaces and classes needed

 

Code snippet

Getting the model element corresponding shape:

 

    PresentationViewsSubject.GetPresentation(modelElement)

        .ForEach(pel =>

            {

                ShapeElement shape = pel as ShapeElement;

 

                //TODO: use shape

            });

Getting the model element corresponding shape:

 

    ModelElement modelElement = PresentationViewsSubject.GetSubject(shape);

 

    //TODO: use model element

 

Assemblies needed

  • Microsoft.VisualStudio.Modeling.Sdk.Diagrams

 

Stay tuned,

Pablo

posted Wednesday, August 20, 2008 11:55 AM by pga with 1 Comments

TTxGen on MSDN Code Gallery

TTxGen is a generic single file generator based on the text templating engine.

What is that???, Some background:

Single file generators or custom tools are COM components registered with Visual Studio that generate code.

To implement a custom tool you basically need to implement the IVsSingleFileGenerator interface. For more detail you can read kzu's post 

A custom tool also needs to be registered and associated to file a extension.

The IVsSingleFileGenerator interface declares two methods:

int DefaultExtension (
	out string pbstrDefaultExtension
)

This method is used to specify the extension of the generated file.

int Generate (
	[InAttribute] string wszInputFilePath,
	[InAttribute] string bstrInputFileContents,
	[InAttribute] string wszDefaultNamespace,
	[OutAttribute] IntPtr[] rgbOutputFileContents,
	out uint pcbOutput,
	[InAttribute] IVsGeneratorProgress pGenerateProgress
)

This method is used to generate the code that we want. It receives the name of the file associated with custom tool, the content of the file and it returns a Byte[] with the generated code.

One serious drawback is that we need to implement, register and deploy one custom tool for each representation of custom code that we want to generate.

Ok that's all for custom tools, now the funny part...

As you may know the text templating (t4) engine is now part of Visual Studio 2008. Based on this I created an implementation of a generic single file generator using t4.

The idea here is to have the same context as in custom tools. For that I have created a custom directive processor that injects the context needed on the tt:

<#@ output extension=".xml" #>
<#@ ParentFileInjector processor="TTxGenDirectiveProcessor" requires="fileName='Sample.xml'" #>
<#= this.ParentFileName #>
<#= this.ParentFileContent #>

If we want to access the parent file name we can use the ParentFileName variable, and for the content we can use the ParentFileContent.

TTxGen comes with some tooling to create a xGen template with the proper directives and context to start generating code:

scn1

scn2

The Create xGen Template command unfold a tt template, default the extension to the extension of the parent file and it automatically replace the requires argument.

 

You can download TTxGen from codegallery.

 

Pablo

posted Monday, February 04, 2008 6:10 PM by pga with 15 Comments

Enabling C# or VB 3.5 inside a text template

What about adding any C# 3.5 feature (linq, extension methods, partial methods, etc) inside a text template file?

The procedure is really easy, just add the "C#v3.5" or "VBv3.5" to the language directive:

<#@ template language="C#v3.5"#>
<#@ Import Namespace="System.Linq" #>
<#@ Assembly Name="System.Core, Version=3.5.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" #>

Happy code generation...

Pablo

posted Tuesday, January 22, 2008 10:38 AM by pga with 4 Comments

Software Factories Toolkit is OUT!!!

The first CTP of the SFT or Clarius Software Factory Toolkit was released yesterday.

It has a lot features that will help you to author a guidance package:

  • VB Net support (Create a guidance package using VBNet)
  • DSL integration (Integrate your recipes with DSLs)
  • Eventing (Launch recipes based on VS events)
  • Scripting (Use the script value provider to assign values to recipe arguments inline)
  • Possibility to register a guidance package on the VS Exp Hive
  • Fixes for GAX known issues:
    • .gpstate and TFS issue fixed
  • and much more...

Please download it now and tell us your story. You could win a free MSDN Team Suite subscription.

On the next posts I will cover in more detail some of these features.

 

Pablo

posted Tuesday, December 19, 2006 6:15 AM by pga with 0 Comments

Integrating DSL RTM and GAX part four

As part of the DSL and GAX posts regarding integration, I would like to recommend an article made by Victor and Mauro named Guidance Automation Toolkit and Domain-Specific Language Tools for Visual Studio 2005: Integration Scenarios.

It describes the process of integrating both technologies, I provided some tips of my previous posts: Integrating DSL RTM and GAX part one , Integrating DSL RTM and GAX part two ,  Integrating DSL RTM and GAX part three

A must read...

Pablo

posted Thursday, November 09, 2006 10:03 AM by pga with 0 Comments

Integrating DSL RTM and GAX part three

On the part two, I talked about launching recipes from the DSL Designer.

Another posibility is to launch a recipe from the DSL Language Explorer. For that we need the command bar GUID and ID.

The good news is that the commandbar GUID is the same that the one for the DSL Designer

The ID for the Language Explorer will always be 65537.

DSLLangExplorer.JPG

 

Pablo

posted Wednesday, October 18, 2006 11:49 AM by pga with 1 Comments

Integrating DSL RTM and GAX part two

Once we have the guidance package and the DSL package living on the same visual studio hive one thing that we will need for sure is the ability to launch recipes from the DSL designer.

For that we need to find out the command bar GUID of the DSL designer.

Steps:

  • Open the DSL solution
  • Open the Constants.cs file located under the DslPackage.csproj
  • Look for:         

    internal static partial class Constants

    {

        // Menu identifier

        public const string Language1CommandSetId = "a00ac613-8df8-4537-b7c7-89d31a44651c";

    }

  • Update the HostData section of the recipe manifest

  < HostData >

    < CommandBar Guid ="a00ac613-8df8-4537-b7c7-89d31a44651c"ID="65536"/>

  </ HostData

 

      Notice that the ID for the DSL RTM version will always be 65536.

 

Pablo

posted Monday, October 09, 2006 9:39 AM by pga with 5989 Comments

Integrating DSL RTM and GAX part one

A guidance package and a DSL package are registered by default in different visual studio hives. A guidance package lives on the main hive and a DSL package lives on the Experimental one.

So the first thing that we need to do is migrate one of the packages so the live on the same hive.

I am going to migrate the DSL package to the main hive, the procedure is very simple:

A DSL solution consists of 2 projects, the Dsl.csproj and DslPackage.csproj and we need to edit both:

Dsl.csproj:

Change the line:

  <PropertyGroup>
    <StartProgram>$(DevEnvDir)\devenv.exe</StartProgram>
    <StartAction>Program</StartAction>
    <StartArguments>/rootsuffix Exp /DesignTimeRun "..\..\..\Debugging\Debugging.sln"</StartArguments>
  </PropertyGroup>

To

  <PropertyGroup>
    <StartProgram>$(DevEnvDir)\devenv.exe</StartProgram>
    <StartAction>Program</StartAction>
    <StartArguments>/DesignTimeRun "..\..\..\Debugging\Debugging.sln"</StartArguments>
  </PropertyGroup>

DslPackage.csproj:

Change the line:

  <PropertyGroup>
    <StartProgram>$(DevEnvDir)\devenv.exe</StartProgram>
    <StartAction>Program</StartAction>
    <StartArguments>/rootsuffix Exp /DesignTimeRun "..\..\..\Debugging\Debugging.sln"</StartArguments>
  </PropertyGroup>

To

  <PropertyGroup>
    <StartProgram>$(DevEnvDir)\devenv.exe</StartProgram>
    <StartAction>Program</StartAction>
    <StartArguments>/DesignTimeRun "..\..\..\Debugging\Debugging.sln"</StartArguments>
  </PropertyGroup>

And

<TargetRegistryRoot>Software\Microsoft\VisualStudio\8.0Exp</TargetRegistryRoot>

To

<TargetRegistryRoot>Software\Microsoft\VisualStudio\8.0</TargetRegistryRoot>

 

After this changes the guidance package and the DSL will live in the same visual studio hive, which means that one is going to be "visible" by the other and viceversa.

 

Pablo

posted Monday, October 09, 2006 9:17 AM by pga with 1 Comments

Executing a GAT recipe from the DSL surface area

To execute a recipe you need to find out which is the GUID for the DSL. This GUID is different for every DSL project that we create.

So, you need to open the GeneratedCmd.cs class file located at \Shell on the Designer project and search for the following constant:

public const string guidDSLNAMEMenuString = "GUID";

For example if we have a DSL named DSLFoo, then we need to search for the constant named guidDSLFooMenuString.

Once we have the GUID, we need the ID. For the DSL menu it will always be 256.

If we supose that we have a guidDSLFooMenuString constant with a value of  “d309f791-903f-11d0-9efc-00a0c911004f“, then the CommandBar will be:

<CommandBar Guid="d309f791-903f-11d0-9efc-00a0c911004f" ID="256"/>

Pablo

posted Wednesday, April 05, 2006 3:11 AM by pga with 1 Comments

T4 syntax coloring and Intellisense!!!

Gaston Milano developed an addin fron Visual Studio 2005, to support intellisense and syntax coloring for T4 Templates.

It works really great.

Pablo

posted Sunday, March 19, 2006 2:08 PM by pga with 1 Comments

T4 Syntax for DSL Tools

I've found a great post about T4 syntax.

http://blogs.msdn.com/garethj/archive/2005/06/01/T4Syntax.aspx

Pablo

 [Via GarethJ's WebLog]

posted Thursday, November 03, 2005 12:33 AM by pga with 3 Comments