So I've tidied up the source for the DSL from my last post a little... though my "test" was to represent a DSL similar to the one Ayende displayed in Brail - I haven't implemented any monorail view engine integration, there's little point I feel, I was more interested in being able to display a nested DSL-like syntax, and parse the necessary information out of it as required.
You can grab it from SVN repository here (edit: I've now fix the PROPFIND proxy issue, so the link should work)
At any rate, probably the most interesting example is the one that takes this code:
var people = new List<Person>()
{
new Person() { FirstName = "Alex", LastName = "Henderson"},
new Person() { FirstName = "Joe", LastName = "Bloggs"}
};
var compDsl = new ComponentDsl();
compDsl.Add
(
GridComponent => compDsl.Component
(
compDsl.Parameters
(
source => people
),
header => compDsl.Section
(
tr => compDsl.As
(
th => compDsl.As
(
compDsl.Text("Names")
)
)
),
item => compDsl.Section
(
tr => compDsl.As
(
td => compDsl.As
(
compDsl.Item<Person>(p => p.FirstName + " " + p.LastName)
)
)
)
)
);
var dsl = new StandardDsl();
dsl.Add
(
html => dsl.As
(
body => compDsl
)
);
And converts it to this xhtml...
<html>
<body>
<table>
<tr>
<th>Names</th>
</tr>
<tr>
<td>Alex Henderson</td>
</tr>
<tr>
<td>Joe Bloggs</td>
</tr>
</table>
</body>
</html>
You can pretty quickly figure out what's going on by placing a breakpoint on the Execute() method of the StandardDsl class and tracing through all the calls - in essence all the nodes are emitted by calling the top-level Batch delegate which causes a recursive call down the "tree", with the information being emitted as a side-effect to an evaluation scope.
Though I used nodes - effectively creating a structure that's easier to parse, there's no reason why you couldn't make immediate calls to some kind of object, avoiding the need for a second round of parsing - the only trick is that you'd still need to use some kind of scoped stack to push/pop the names of the components because in a statement like this:
dsl.As
(
GridComponent => dsl.Component
(
// etc. etc.
)
)
the call to dsl.Component needs some way to inspect the stack of names and pull "GridComponent" off the top.
I'd love to hear from anyone who could see a use for this kind of thing... it'd be nice to get a more realistic example... I'm struggling to think of anything practical myself.
[Edit: I Noticed the code formatting was pretty awful, so I've tidied it up a little... anyone got a good solution for copy/pasting code out of orcas (CopyAsHtml2005 doesn't appear to install under Orcas)]