XAML Code Generation Markup Language

I have a very simple working prototype of the XAML Code Generator that I was discussing in my last post. It turns out that it’s totally possible! So for example if you have XAML that looks like this:

<test:Parent xmlns=”clr-namespace:Xcgml;assembly=Xcgml”

     xmlns:test=”clr-namespace:Xcgml.Testing.Mock;assembly=Xcgml.Testing” >

     <test:Child Data=”{Binding}” />

</test:Parent>

What we have here are two classes that inherit from GeneratorElement (which inherits from DependencyObject) and one other class called Binding that inherits from MarkupExtension. After running this XAML through the XamlReader, you end up with deserialized objects.

public static GeneratorElement Load(string xaml)

{

    using (TextReader reader = new StringReader(xaml))

    {

        using (XmlReader xmlReader = XmlReader.Create(reader))

        {

            ParserContext context = new ParserContext();

            context.XmlLang = “xcgml”;

 

            return (GeneratorElement)System.Windows.Markup.XamlReader.Load(xmlReader);

        }

    }    

}

The interesting thing is the binding. It turns out that there is no automatic system for resolving bindings like I had hoped but fortunately it’s possible to implement your own. It seems like a lot of what we get seemingly for free in WPF sits on top of the FrameworkElement class. The framework element class is not available for this scenario; I must implement my own elements on top of DependencyObject. However it wasn’t very hard to figure out how to propagate the DataContext and how to refresh values based on bindings. Here is an example unit test:

[TestMethod]

public void Simple1()

{

    Parent element = XamlReader.Load(Resources.Simple1) as Parent;

    Assert.IsNotNull(element);

    Assert.IsNotNull(element.Content);

    Assert.IsInstanceOfType(element.Content, typeof(Child));

 

    string expected = “success”;

    element.DataContext = expected;

    string actual = (element.Content as Child).Data;

 

    Assert.AreEqual(expected, actual);

}

Notice when I set the element.DataContext the child’s Data property will change because of the binding specified! I am planning on adding these features soon:

<!–[if !supportLists]–>·         <!–[endif]–>StaticResource binding – so you can bind to values in resources

<!–[if !supportLists]–>·         <!–[endif]–>Templates – so you can customize standard objects

<!–[if !supportLists]–>·         <!–[endif]–>ItemsControl – so you can have multiple nested controls

<!–[if !supportLists]–>·         <!–[endif]–>Repeat control

<!–[if !supportLists]–>·         <!–[endif]–>If control

 

Download the Source

<!–[if !supportLists]–>·         <!–[endif]–>Xcgml-20080731.zip (17.2 KB)

XAML View Engine

I just had an interesting idea and wanted to blog it down before forgetting since I can’t really spend time investigating it now.

Well I’ve been working with NVelocity and now Spark to use as my view engine for template generation. I’m very happy with Spark right now (since it actually works) and I have been generating templates like a fool the last couple days. I think I might have a preview release of NBusiness 3 out for testing sometime soon.

That being said there is definitely still something missing. It works… it’s a heck of a lot better than NVelocity but it’s not quite perfect. I was just mentioning this to a friend and suddenly had a jolt of inspiration. I had the idea that you could, quite possibly, declare your entire template in XAML . Your XAML syntax could support binding and you could have looping and conditional controls right in it. This would allow you to declaratively define code in arbitrary languages. Pretty interesting… here is a little snippet of what I was envisioning:

<Class Attributes=”Public, Abstract” Base=”BusinessBase” Name=”{Binding Name}”>

   <Repeat Collection=”{Binding Fields}”>

      <Field Name=”field” Attributes=”Private” Type=”{Binding Path=Type}” Name=”{Binding Path=Name, Converter=FIeldNameConverter}” />

      <Property Attributes=”Public” Type={Binding Path=Type}” Name={Binding Path=Name}”>

         <Property.Getter><Return Expression=”{Binding RelativeSource=field}” /></Property.Getter>

      </Property>

   </Repeat>

  

</Class>

Honestly, I’m thinking that all I have to do is create these objects which would inherit from DependencyObject and the XAML serializer will do the rest… I doubt it would be that simple but I may have to try it out later tonight.

The thing is, once you have this template into a DOM you could then run it through some sort of Conversion process to create CodeDom objects which would produce code for any arbitrary language! The trick would be to make it flexible enough to support conversion to things like HTML or whatever. Wow, this could be interesting.

Boo Shirts

I think I am going to order some boo shirts, I want one for myself and I’ll probably give a few away at my upcoming boo presentations so I’ll order in bulk. Here’s the shirt:

If anyone wants one let me know because I can get them a little bit cheaper since there is a discount for bulk ordering. Send me an email directly with the following information:

  • Your name
  • Your mailing address
  • Shirt size

We’ll work out payments be it through pay pal or some-other means. The price of the shirt will be exactly what I paid to have them made plus shipping. The more people who want one the cheaper they will be. If you’re willing to pay for international shipping than I’m willing to send it!

[EDIT] The cafe press widget I was linking to was broken so I just swapped it out with a picture of the actual shirt. See representing boo for more. I can still order more if you want.

Spark view engine

If you’re interested in the new Microsoft MVC framework but you’re a little skeptical about going back to a classic ASP Tag Soup rendering system, you should check out the Spark View Engine.

It has a very interesting way of allowing you to write your view with some simple string replacements and also specialized tags that appear to be actual HTML. The general idea is basically the same but visual appeal is quite a bit better.

Here is an example:

<var names=“new [] {‘alpha’, ‘beta’, ‘gamma’}”/>

<for each=“var name in names”>

  <test if=“name == ‘beta'”>

    <p>beta is my favorite.</p>

    <else/>

    <p>${name} is okay too I suppose.

  </test>

</for>

 In this case your “foreach” loop appears to actually be part of the html. The code inside of the each attribute is compiled as C#.  The system it uses is pretty straightforward and easy to understand which gives me a lot of confidence in it already.

I have been having problems getting NVelocity to work properly so I am going to try to use Spark as the default NBusiness code generation tool. We’ll see how intuitive it is to have this pseudo-html markup inside of code but I suspect this tool will work much better for NBusiness.

ESharp Validation Rule Breakthrough

After a late night of hacking I have finally got an end to end transformation of E# validation rules into CSLA code that compiles. I am using the NVelocity code generator I created to do this, here is the example entity I have defined:

using NBusiness.Frameworks.Csla.Templates;

using Csla.Validation.CommonRules;

 

family Test

{

      entity A as EditableRoot

      {

            field auto id int aid;

            field nullable string data;

            field nullable double value;

           

            validate data StringMaxLength { MaxLength : 10 };

      }

}

 

After running this through the compiler here is the code that it generated:

using System;

using Csla;

using Csla.Validation;

using System.Collections.Generic;

 

namespace Test

{

      [Serializable]

      public partial class A : BusinessBase<A>

      {

            #region Properties

            private static PropertyInfo<int> aidProperty = RegisterProperty<int>(

                  typeof(A),

                  new PropertyInfo<int>(“aid”));

            /// <summary>

            /// aid property

            /// </summary>

            public int aid

            {

                  get { return GetProperty<int>(aidProperty); }

            }

            private static PropertyInfo<string> dataProperty = RegisterProperty<string>(

                  typeof(A),

                  new PropertyInfo<string>(“data”));

            /// <summary>

            /// data property

            /// </summary>

            public string data

            {

                  get { return GetProperty<string>(dataProperty); }

                  set { SetProperty<string>(dataProperty, value); }

            }

            private static PropertyInfo<System.Nullable<double>> valueProperty = RegisterProperty<System.Nullable<double>>(

                  typeof(A),

                  new PropertyInfo<System.Nullable<double>>(“value”));

            /// <summary>

            /// value property

            /// </summary>

            public System.Nullable<double> value

            {

                  get { return GetProperty<System.Nullable<double>>(valueProperty); }

                  set { SetProperty<System.Nullable<double>>(valueProperty, value); }

            }

            #endregion

 

            #region Relationships

            #endregion

           

            #region Validation

            protected override void AddBusinessRules()

            {

                  Dictionary<string, object> dataArgs = new Dictionary<string, object>();

                  dataArgs.Add(“MaxLength”, 10);

                  ValidationRules.AddRule(

                        Csla.Validation.CommonRules.StringMaxLength,

                        new DecoratedRuleArgs(dataProperty, dataArgs));

            }

            #endregion

      }

}

(You can see the power of a DSL simply by looking at how many more lines of code it takes to represent the same thing in a lower level language!)

It has taken me a loooong time to get to this point and I think it’s all downhill from here. Trying to find out how to discover validation / access / authorization rules from arbitrary business object frameworks turns out to be a terribly difficult thing to do. There is lots of room for improvement but I think I have the basics down for now. This should allow me to generate code for CSLA and NBusiness frameworks at least and perhaps a couple of others without too much work.

Next up is largely a process of cleaning up code (I have been hacking on things a lot recently), fixing up unit tests and fleshing out CSLA templates for each major stereotype (I love that word in a software context!). What a relief!