Done? Good, let's go forward.
Requirements for running the program are Visual Studio 2010 Release Candidate and SQL Server Modeling tools.
Note. Since my previous post the SQL Server Modeling version has been upgraded to work with Visual Studio 2010 Release Candidate, so if you haven't upgraded to RC before, now is the time. Though if you're unwilling to upgrade currently, the examples should also work with VS2010 Beta2 and SQL Server Modeling Nov2009 CTP.
-==- Using the model -==-
Using the simple "M" Grammar we created in the previous post we now can use it from inside code.
First, we'll create a "Oslo library" project and then create a "M" Language file.

Now we can copy our previous model inside the created MG-file (M Grammar).
Then let's create a console project that will use the model to parse some data.
First, add references to SSM libraries:
- Xaml.dll
- Microsoft.Oslo.Internal.dll
These can be found in directory c:\Program Files\Microsoft Oslo\1.0\bin\
Next, to dynamically use the model, we'll use Pinky's (and Don Boxes) sample code from he's post.
The code is a proof of concept used on PDC 2009 session.
I added a few functions to more easily get child attributes and values, but basically they just lightly build on the basic functionality that exists in Pinky's prototype, so I'm not going to go over that (as it's also undocumented).
-==- Let's see the code -==-
Loading and parsing:
// read the data
string input = File.ReadAllText(@"data.m");
// load the assembly containing the model
var assembly = Assembly.LoadWithPartialName("Model.Lib");
// load the Module.Language from the assembly
var language = new Language(assembly, /* Module: */ "Model", /* Language: */ "Model");
// parse input data into a tree structure
dynamic root = language.ParseString(input);
Result is the root node of our tree structure. Our structure is the following:Models
+ Model
+ Name
+ Entities
+ Entity
+ Name
+ Attributes
+ Attribute
+ Name
+ Type
If you haven't check Intellipad yet, check it out and check what we did on the previous post.

To get all the models, and there can be multiple, we can simply loop them with
foreach (dynamic model in root.GetChildNodesByType("Model"))
The Model itself does not contain any values, but contains subnodes Name and Entities. To get to the name value we'll take the Name subnode and get it's internal valuedynamic nameValue = model.GetChildNodeByType("Name").GetValue();
And in a similar vein we'll continue printing the whole graph
// Go through all Entity nodes within Entities collection
foreach (dynamic entity in model.GetChildNodeByType("Entities"))
{
// Similarly as with models, get Entity's name from Name subnode's value.
System.Console.WriteLine(" " + entity.GetChildNodeByType("Name").GetValue());
// Go through all Attribute nodes within the Entity.
foreach (dynamic attribute in entity.GetChildNodeByType("Attributes"))
{
System.Console.WriteLine(" {0}: {1} ({2})",
// Get Attribute's Name node and from within, it's value.
attribute.GetChildNodeByType("Name").GetValue(),
// Get Attribute's Type node and from within, it's first value.
attribute.GetChildNodeByType("Type").GetValues(1),
// Get Attribute's Type node and from within, it's second value.
attribute.GetChildNodeByType("Type").GetValues(2)
);
}
}
-==- Results using sample data -==-
Running this with my dataset..
ModelName {
"Entity1 With space" {
"Attribute1" Text(100),
"Attribute2" Number
},
Entity2withoutspace {
"Attribute with space" Text(255),
Attributewithoutspace Number
}
},
ModelName2 {
"Entity2" {
Attribute2 Text(100),
Attribute3 Number
},
Entity3 {
"Attribute4" Text(255)
}
}
..we get the result
ModelName
Entity1 With space
Attribute1: Text (100)
Attribute2: Number (0)
Entity2withoutspace
Attribute with space: Text (255)
Attributewithoutspace: Number (0)
ModelName2
Entity2
Attribute2: Text (100)
Attribute3: Number (0)
Entity3
Attribute4: Text (255)
And of course, you can recursively walk the graph
public static void Walk(dynamic node, int depth = 1)
{
// print nodes type
System.Console.WriteLine("{0:##}{1}{2}", depth, "".PadLeft(depth, '.'), node.GetBrand());
// loop through all the values in node
foreach (dynamic value in node.GetValues())
{
System.Console.WriteLine(string.Format("{0:##}{1}==>{2}", depth, "".PadLeft(depth, ' '), value));
}
// loop through all subnodes
foreach (dynamic childNode in node.GetChildNodes())
{
Walk(childNode, depth + 1);
}
}
First column is the level of the node.2..Model means we are on level 2 of the graph and there's an node named Model.
Values in the node are described with ==>Value notation. For example, on Models.Model.Name (see row 4 below) we have ModelName as the value of the Name node.
1.Models 2..Model 3...Name 3 ==>ModelName 3...Entities 4....Entity 5.....Name 5 ==>Entity1 With space 5.....Attributes 6......Attribute 7.......Name 7 ==>Attribute1 7.......Type 7 ==>Text 7 ==>100 6......Attribute 7.......Name 7 ==>Attribute2 7.......Type 7 ==>Number 7 ==>0 4....Entity 5.....Name 5 ==>Entity2withoutspace 5.....Attributes 6......Attribute 7.......Name 7 ==>Attribute with space 7.......Type 7 ==>Text 7 ==>255 6......Attribute 7.......Name 7 ==>Attributewithoutspace 7.......Type 7 ==>Number 7 ==>0
-==- Source -==-
That's it this time. MIX 2010 is devouring my blogging time.
As usual, the source can be found here.
0 comments:
Post a Comment