January 20, 2021
Hot Topics:

Building a WPF Animation DSL Using M and the Oslo SDK

  • By Jeffrey Juday
  • Send Email »
  • More Articles »

Bringing MGrammar into the Application

Rather than building code to open the MGrammar file to read the code, I chose to add the MGrammar file to my Visual Studio project and make my MGrammar code an embedded resource. The embedded resource property is highlighted in Figure 3 below.

Figure 3 WPFTestingWithMG properties

A DynamicParser object must be constructed from the Resource. DynamicParser is a new class shipping with the Oslo SDK. DynamicParser is in charge of generating the MGraph. MParserBuilder constructs the DynamicParser from the WPFTestingWithMG resource. MParserBuilder's Build function appears below.

public void Build(string resourceName)
   var assembly = Assembly.GetExecutingAssembly();
   using (var stream = assembly.GetManifestResourceStream(resourceName))
   using (var reader = new StreamReader(stream))
      var errorReporter = ErrorReporter.Standard;
      var compiler = new MGrammarCompiler
         SourceItems = new SourceItem[] { 
            new SourceItem { 
                 Name = "MGrammarInterpreter Grammar", 
                 ContentType = ContentType.Mg, 
                 TextReader = reader,
      if (compiler.Compile(errorReporter) != 0 || errorReporter.HasErrors)
         throw new Exception("Failure compiling WPFTestingWithMG.mg");

Build reads the code from the embedded resource, compiles the MGrammar code, and associates the complied code with the DynamicParser.

The next task was to programmatically generate MGraph from the DynamicParser.

Generating MGraph

MGraphGenerator feeds the DSL code to the DynamicParser object to generate the MGraph. MGraphGenerator Run function appears below.

public void Run(string inputText,DynamicParser parser)
   ExceptionErrorReporter errorReporter;
   parser.GraphBuilder = _builder;
   errorReporter = new ExceptionErrorReporter();
   GraphRoot = parser.Parse<object>(string.Empty, 
           new StringReader(inputText), errorReporter);
   if (GraphRoot == null || errorReporter.HasErrors)

GraphBuilder contains the data resulting from the parsed DSL code. GraphBuilder is a collection of object classes. GraphBuilder includes a set of functions for adding and traversing the object collection. GraphBuilder is hierarchal with a root and multiple child elements. GraphBuilder is a little clunky to use. I'm hoping future versions of the Oslo SDK will include a richer MGraph consumption experience or more guidance on constructing your own GraphBuider.

You may have noticed that I bypassed building MSchema. In its current incarnation, MSchema is associated more with SQL Server and the Oslo Repository. Since I'm not utilizing the Oslo Repository, I did nothing with MSchema.

Reading and consuming GraphBuilder is the job of the MGraphReader class.

Consuming MGraph

MGraphReader pulls the data from a GraphBuilder. A snippet from the MGraphReader WalkTheNodes function appears below.

private void WalkTheNodes(System.Dataflow.GraphBuilder graph, 
       object nodeOn, List<Move> list)
    List<object> vals;
    string MoveX = "";
    string MoveY = "";
    string seqLabel = "";
    object seqLabelObj = null;
    List<object> tempPos;
    Move moveObj = null;
    bool isNode = false;
    double moveOffset = 3.0;
    double moveMultiplier;
    foreach (object enumNext in graph.GetSuccessors(nodeOn))
       isNode = graph.IsNode(enumNext);
       if ((isNode)) //Skip the non-nodes
          seqLabelObj = graph.GetSequenceLabel(enumNext);
          if (seqLabelObj != null) //Sometimes label returns null value
             seqLabel = seqLabelObj.ToString();
             if (seqLabel == @"Move") //You reach a Move label
                 //Successors of Move are MoveX, MoveY, and Mult
                 vals = graph.GetSuccessors(enumNext).ToList<object>();
                 //ToList converts IEnumerable to List generic
                 //MoveX Successor is the MoveX value
                 tempPos = graph.GetSuccessors(vals[0]).ToList<object>();
                 MoveX = tempPos[0].ToString();
          WalkTheNodes(graph, enumNext, list);

WalkTheNodes recursively visits the nodes on GraphBuilder, building a list of Move objects required by the EllipseAnimator class discussed earlier in the article. The Nodes labeled "Move" and successors below the "Move" nodes contain the runtime's data.

GraphBuilder functions getting node objects return objects based on the IEnumerble interface. To move GraphBuilder data into List collections, MGraphReader employs .NET classes working with IEnumerable interfaces.


This sample application shows how M and the Olso SDK can be incorporated into a Visual Studio application. Using MGrammar I built a DSL to configure an animation. I also built a WPF animation runtime for consuming data emitted by the MGrammar DSL.

Source Code

The source code for this article: MGrammarInterpreter.zip.

About the Author

Jeffrey Juday is a software developer specializing in enterprise integration solutions utilizing BizTalk, SharePoint, WCF, WF, and SQL Server. Jeff has been developing software with Microsoft tools for more than 15 years in a variety of industries including: military, manufacturing, financial services, management consulting, and computer security. Jeff is a Microsoft BizTalk MVP. Jeff spends his spare time with his wife Sherrill and daughter Alexandra. You can reach Jeff at me@jeffjuday.com.


Martin Fowler's DSL work

Oslo SDK documentation

WPF Animation Documentation on MSDN

Oslo development center Samples and Documentation

Page 3 of 3

This article was originally published on April 7, 2009

Enterprise Development Update

Don't miss an article. Subscribe to our newsletter below.

Thanks for your registration, follow us on our social networks to keep up-to-date