Monday, May 06, 2013

XAML as DSL

About 3 years ago, when .NET 4 and Visual Studio 2010 were just released, I've blogged (part 1, part 2) about the changes that took XAML from its WPF inception to the System.Xaml namespace and System.Xaml.Dll assembly, to be available more generally, not just for WPF. I've shown that XAML is just a declarative way of creating objects, setting their properties – sometimes in interesting ways. I did promise at the end of that second post that I'd show how to use attached properties, but never did have the time to deliver. 3 years later, it's high time I make good on that promise.

The idea of a Domain Specific Language (DSL) is not new. Probably the most well known DSL is SQL – a language for working with databases. A DSL is typically constrained to a specific domain or a specific task (hence the name). A DSL may be a completely new language (such as SQL), and this is termed "external DSL", and it can be constructed using a specific language semantics, such as C#, by leveraging certain language features that make up the "new" language. in C#, extension methods and "fluent interfaces" are most often used for that task.

What about XAML? The declarative nature of XAML makes it a good candidate to be a DSL. It has simple and strict rules, but it allows extensions, with type converters, markup extensions and attached properties.

An example
Suppose we want to create a text adventure game ("interactive fiction") language (yes, I know I have a fetish for text adventures…). We could use XAML to describe not just the world that comprises the game, but also the actions that need to take place in certain scenarios.

The first step is to create an object model suitable to describe a text adventure. Here are a few simple classes to get us started:

[Serializable]
[DictionaryKeyProperty("Name")]
[DebuggerDisplay("{Name}")]
public abstract class Entity {
    Dictionary<string, object> _properties;
 
    public string Name { get; set; }
    public IDictionary<string, object> Properties {
        get {
            return _properties ?? (_properties = new Dictionary<string, object>(4, StringComparer.CurrentCultureIgnoreCase));
        }
    }
}


Read more: Pavel's Blog
QR: Inline image 1