Mapping CLR Namespaces to XML for XAML
In my work on a WPF version of Comicster, I have a few assemblies that I want to reference from my XAML. For example, the Comicster.Core framework assembly (whose CLR namespace is simply “Comicster”) contains the collection classes such as Title, Issue, Character and Creator. The Comicster.Windows.Core assembly (which contains namespaces under “Comicster.Windows”) contains the WPF-specific bits like a thumbnail control, custom RoutedUICommands and IValueConverter implementations.
I soon got tired of mapping the various CLR namespaces to XML namespaces using this construct:
xmlns:c="clr-namespace:Comicster;assembly=Comicster.Core"
It works, but it just doesn’t feel like XAML, especially when you find this just above that in the same XAML file:
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
That’s the sort of thing I wanted to do. So, after a bit of reading, I discovered the XmlnsDefinitionAttribute. You can decorate your assembly with this attribute, and it essentially maps a URI-based XML namespace to your CLR namespace! Just add this to your AssemblyInfo.cs file:
[assembly: XmlnsDefinition("http://comicster.net/2008", "Comicster")]
Now my Comicster namespace (in Comicster.Core.dll) maps nicely to the given URI (which doesn’t have to be a proper resource on the net), and I can replace that namespace declaration at the top of this post with this:
xmlns:c="http://comicster.net/2008"
So that’s just dandy, but there was one last thing bugging me. In my Comicster.Windows.Core assembly, I have a whole slew of namespaces. Comicster.Windows.Converters, Comicster.Windows.Controls, Comicster.Windows.Input etc. I didn’t want all of those namespaces to map to their own URI (and therefore have to have individual xmlns declarations in my XAML file), I wanted them all to get lumped under the same URI like the “x” namespace that maps to the WinFX schema above. I was this close to posting a question on Stack Overflow to ask how to do it, when I thought I’d try this:
[assembly: XmlnsDefinition("http://comicster.net/2008/windows", "Comicster.Windows.Controls")] [assembly: XmlnsDefinition("http://comicster.net/2008/windows", "Comicster.Windows.Converters")] [assembly: XmlnsDefinition("http://comicster.net/2008/windows", "Comicster.Windows.Input")]And guess what? It worked! It turns out that you can just merge all your CLR namespaces into one easy-to-use XML namespace like that. This makes it very easy to code up a “framework” that others can use without having to remember where all the bits live. In a lot of ways, the old adage that applied to NetHack applies to the .NET Framework: “The devteam thinks of everything!”