So it goes with the digestive processes of programming trends, and dynamic delegation has reached the crowded mainland shores of the .NET Framework in the form of C# 4‘s dynamic type. Though it was nothing new even then, six years ago many of us got our first hit of dynamic delegation through Ruby metaprogramming in Rails. The very notion that something like this:
was enough to provide a rich API over a
users database table supporting calls like the following was mind-opening at the time.
Really? Yep, with Ruby’s
But the caffeine wears off, you buy a house in the suburbs, and you have to debug your fancy meta-code. JRuby core developer, Ola Bini writes:
In almost all cases you think you need
method_missing, you actually don’t.
I never use
method_missing. Maybe twice. And both times I didn’t use it, regretted it, forcefully ejected the code from a moving vehicle, shed nary a tear.
And yet, there’s so many great uses for
method_missingout there. If I may, a few of my favorite
comment!, None of the methods called on the
xml object exist, and are instead resolved into element names at runtime. So we end up with a simple, declarative, XML generation DSL that doesn’t care about the schema it’s generating.
Hey, that’s useful.
So, now with C# 4‘s dynamic type and the DynamicObject class, .NET has a mostly-workable
method_missing of its own. And with the help of a smidgen of code that is DynamicBuilder, we can accomplish the same API.
You can learn it in five minutes and integrate it into existing code in even less time as it’s just a single small class.
Nodes via dynamic invocation
Attributes via anonymous objects
Nesting via anonymous delegates
Putting it all together: building an Atom syndication feed
Shoulders of Giants
Well, that’s all nice I guess, but the last thing you want is more XML, right? What about other .NET XML APIs? How is this any better?
The System.Xml Ghetto
The mean streets. Power and control meets, well, nothing. The original
System.Xml types, with us since the beginning of .NET, can be quite tedious to manipulate directly and have grown anachronistically low-level.
While these types still are behind the scenes of all subsequent .NET XML APIs (including DynamicBuilder), their verbose syntaxes mean they are no longer the best option for direct XML creation.
The System.Xml.Serialization Suburbs
Medicated and mostly harmless. This is an attractive choice when your serializable types map exactly to the XML you wish to generate. Otherwise, I hope you like creating boilerplate adapter classes just for serialization, or that you actually enjoy XSLT.
DynamicBuilder allows code that is just as terse as a serializable class while still retaining the flexibility of manually generating specific XML content.
The System.Xml.Linq New Urbanism
Attractive but superficial. C# 3.0 introduced LINQ to XML, and with it, the
System.Xml.Linq types. This revolutionized both the programmatic querying of XML as well as the declarative construction of it via object initialization.
While a significant improvement, it can still be awkward and unnatural to use when the document must be generated logically, as everything must be declared via object initialization. DynamicBuilder’s choice of anonymous delegates over object initialization allows for all manner of imaginable logic to be employed within a single, unified, XML creation block. Coupled with DynamicBuilder’s anonymous object-to-attributes mapping, and the syntax is also much thinner and closer to the resulting markup than nested
LINQ to XML is still probably the simplest XML querying/consumption mechanism. Also,
DynamicBuilder.Xml actually uses
System.Xml.Linq types internally to model its XML, and can easily expose it via its
What about Document Types, Comments, and Namespaces?
In as much as System.Xml.Linq supports them, so does DynamicBuilder. Check the doc.
Ok, but what’s with that ugly
Well, you got me there. Dynamic operations in C# 4 can do nearly anything: method calls, properties, even executing the dynamic object as a delegate. Unfortunately, those dynamic method calls cannot accept anonymous lambdas. Admittedly, this would have been so much better:
And it’s what Builder does. Sadly,
Error: Cannot use a lambda expression as an argument to a dynamically dispatched operation without first casting it to a delegate or expression tree type.
And just like that, so many Ruby-ish DSLs will never see the light of day. Instead we would have to cast the lambda:
To counteract that ugliness just a bit, the static helper
Xml.Fragment() hides the cast.
Since it’s just a single class, you could simply copy
Xml.cs directly into your project. It doesn’t really warrant the overhead of being a referenced assembly.
- Download the source, tests, and example from GitHub.
- cd into the project’s directory
> build release
build\Release\Xml.csinto your own project. Alternatively, you could add a reference to
- Either modify
Xml.csto share your project’s namespace, or add the
DynamicBuildernamespace within your code
To run DynamicBuilder’s xUnit test suite, use
Even if this dynamic hipster jazz isn’t your thing, it’s always useful to learn from other languages’ cultural approaches to solving universal programming problems.
DynamicBuilder is a work in progress. Please feel free to fork away.