Martin Murphy and I are planning to release a migrations tool for .NET called Mite. Mite will allow you to write database migrations in the veign of Ruby on Rails in C# or a Boo DSL (Domain Specific Language).
While designing the command line client for Mite, I wanted to use the nice features of DSL to create the environment configurations.
This is the desired syntax:
Why is this better than an XML configuration file?
This settings DSL is actual code. Notice that the type of the adapter is set in a local variable to the typeof a concrete type. There is no need to type an error prone class reference string like "Mite.MsSql.MsSqlAdapter, Mite". Also, we are able to keep it DRY by using local variables. All the features of the boo programming language are available to us. We could create an environment for each assembly in the current directory, name the environment after the assembly name, and use the first IAdapter found in the assembly as the adapter. The possibilities are limitless.
Rhino DSL is an excellent tool developed by Oren Eini. It makes getting started with a Boo DSL much easier and I highly recommend using it if you wish to develop your own DSL.
- Subclass DslEngine from Rhino.DSL as SettingsDslEngine. Add AnonymousBaseClassCompilerStep to the compiler pipeline. Turn duck-typing on.
- Create MiteSettings, the base class that AnonymousBaseClassCompilerStep will use to put the code from the DSL into.
- Create static Settings class to provide an API for use by other programs.
With the help of Rhino DSL, customizing the compiler is trivial. We only need to declare the type of Storage we will be using in the constructor and then override CustomizeCompiler to add the AnonymousBaseClassCompilerStep.
MiteSettings, base class for AnonymousBaseClassCompilerStep
The environment method is the most interesting part of this base class.
The properties in the region "Properties for environment creation" are set by the call to block. Block comes from the "block" in the DSL syntax. A block in boo is like a block in python, it is defined by indentation following a colon. Hence when in the settings DSL we declare an environment and then set values inside of it, the values that we are setting are actually properties on the base class.
To tie it all together, we create a static class to serve as the external API for dealing with the settings configured by the DSL.
Initialize a dsl factory in the static constructor:
Provide a method to load a settings file:
Download the sample project
Mite is not yet completely ready for prime-time, but here is a link to our projects home on google code
. I plan to blog about the development of Mite as the project progresses.