Load a DSL domain model instance file programmatically

Load a DSL domain model instance file programmatically

A lot of people now find themselves working with DSL (domain specific language) model instances. Is there a way to load these files programmatically?

    Requires Free Membership to View

    When you register, you'll begin receiving targeted emails from my team of award-winning writers. Our goal is to provide a unique online resource for developers, architects and development managers tasked with building and maintaining enterprise applications using Visual Basic, C# and the Microsoft .NET platform.

    Hannah Smalltree, Editorial Director

    By submitting your registration information to SearchWinDevelopment.com you agree to receive email communications from TechTarget and TechTarget partners. We encourage you to read our Privacy Policy which contains important disclosures about how we collect and use your registration and other information. If you reside outside of the United States, by submitting this registration information you consent to having your personal data transferred to and processed in the United States. Your use of SearchWinDevelopment.com is governed by our Terms of Use. You may contact us at webmaster@TechTarget.com.

Say you have a custom DSL file in a solution. Say you want to process the model on that file using GAT or an AddIn or even your custom application code at runtime. You need to deserialize that XML (yes, it's all XML in the end) into an instance of your domain model (root).

You will need two pieces of information: the .NET type of the domain model (that is, the parent of your domain model root concept) and its the corresponding designer. The following code does the trick, allowing you to deserialize a model and return the first instance of the given domain model type (i.e. the model root):

public static TRootConcept GetModelRoot(string modelFile, Type modelType, Type designerType)
{
 // Create a new store to deserialize the instance to.
 Store newStore = new Store();
 Type[] metaTypes = new Type[] {
  typeof(Microsoft.VisualStudio.Modeling.Diagrams.CoreDesignSurface),
  typeof(Microsoft.VisualStudio.Modeling.Utilities.UtilitiesModel),
  modelType,
  designerType };

 // Load these types into the store, so that it knows about them for deserialization.
 newStore.LoadMetaModels(metaTypes);

 foreach (Type subStoreType in metaTypes)
 {
  // TODO: this will not be required in RC+ versions of DSL tools.
  Activator.CreateInstance(subStoreType, newStore);
 }

 // Be version resilient
 int majorVersion;
 int minorVersion;
 GetModelVersion(modelFile, out majorVersion, out minorVersion);

 // Deserialize the file into the store
 using (Stream fileStream = File.OpenRead(modelFile))
 {
  XmlSerialization.DeserializeStore(newStore, fileStream, majorVersion, minorVersion, null, null);
 }

 // Locate the attribute that will give you the Guid of the element to find
 MetaObjectAttribute metaObject = Generics.GetCustomAttribute(typeof(TRootConcept));
 if (metaObject == null)
 {
  throw new ArgumentException(String.Format(
   CultureInfo.CurrentCulture,
   Properties.Resources.MetaInformationForElementNotFound,
   elementType));
 }

 // Return the first one we find
 foreach (object element in newStore.ElementDirectory.GetElements(metaObject.Id))
 {
  return element;
 }
 return null;
}

The GetModelVersion helper method simply reads the major/minor values from the XML itself:

private static void GetModelVersion(string modelFile, out int majorVersion, out int minorVersion)
{
 // Get versions from model:
 //<om:MetaModel MajorVersion="1" MinorVersion="1" xmlns:om="http://Microsoft.VisualStudio.Modeling">
 using (XmlReader reader = XmlReader.Create(modelFile))
 {
  reader.MoveToContent();
  if (reader.LocalName != "MetaModel")
  {
   throw new InvalidOperationException(Properties.Resources.FileDoesNotContainModel);
  }
  majorVersion = Int32.Parse(reader.GetAttribute("MajorVersion"), CultureInfo.CurrentCulture);
  minorVersion = Int32.Parse(reader.GetAttribute("MinorVersion"), CultureInfo.CurrentCulture);
 }
}

This expert response originally appeared on Daniel Cazzulino's blog.


Do you have comments on this Ask the Expert question and response? Let us know.

This was first published in March 2006