Emulating Castle Blade's Nested Transitions With Spark
Nested transitions
As described on Hammet’s post, Castle Blade view engine extends Razor’s syntax to allow nested transitions. Those in turn give Blade a great deal of flexibility. The given example being usage of the new FormHelper.
1 2 3 4 5 6 7 8 9 10 11 12 13 |
|
The above is indeed cool but the readability is not great in my opinion. In Spark the above could look like this:
1 2 3 4 5 6 7 8 9 10 11 12 13 |
|
Unfortunately porting the syntax of nested transitions to Spark was not exactly easy. My initial solution was to use macrosmacros. I wrote about it on Spark’s discussions group. However this solution was far from perfect and following Robert’s suggestions I changed the implementation to bindings and helper methods.
Nested tra… what?
Nested transition, or blocks are evaluated as inline lambdas. This means that the some of the XML tags will have to be evaluated as either a compatible method call or it’s body.
In the above example those custom tags are <Form>
, <FormTemplate>
and <Template>
. They correspond to lines 1, 2,
10 and 11 in the Blade code fragment. The above example transforms into something like the following in C#:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
|
The most important parts are indeed the lambda expressions. The tricky part was transforming Spark’s XML to te above-like form.
Bindings to the rescue
For the mentioned transformations needed for this example to work I created 3 transformation. One for each method called \
(ie. Form.For
, builder.FormTemplate
and builder.TemplateFor
):
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 |
|
Bindings transform a nonstandard tag defined by the name attribute into a given form and can take any number of
parameters. It this example <Form>
tag, if supplied for and url parameters transforms into a FormHelper#For call, it’s
content rendered as usually by Spark.
Other uses
I would assume that those nested transitions will be heavily used in Blade and thus the above method could be used heavily when working with the new Monorail’s lambda API.
Because of that these and other bindings are stored in an embedded resource and I have created custom IBindingProvider decorated class, which will combine them with any custom user bindings. This class can be found here.