[Xaml] IoC-enabled Xaml parser

As this post is about a scenario that is not discussed very much even in English, I won’t write this post in French in order to have a broader audience.

WPF and Silverlight are very good candidates for applying IoC concepts. Coupled with MVVM pattern, IoC make it really easier to build testable and robust applications. However, one limitation is that the Xaml language itself does not play well with it (as it’s basically an object graph Serialization / Deserialization language and so it only works with concrete types). So to instantiate data contexts from an IoC container, we need to write code-behind code. This problem is even more annoying for the WF use of Xaml (as with WF4.0, we do not have Code-Behind anymore).

Fortunately, with .Net 4.0, the xaml readers and writers have been completely refactored in a very extensible way. So we are able to provide our own XamlSchemaContext that provides the XamlNodes instantiation logic. The resolution of a type in the .net 4.0 Xaml reader is done through an abstraction layer:

From a given xaml namespace / xaml element name, the XamlSchemaContext is responsible of resolving a XamlType which represents a Clr Type. This XamlType provide a TypeInvoker responsible of the instantiation of a XamlType. By creating a custom XamlSchemaContext that replace the default XamlType resolution by a unity-enabled XamlType / XamlTypeInvoker whenever it finds that the default one is not capable of creating the requested object, we can rely on the container to resolve these types.

So we’ll be able to parse things like that:

<Window xmlns=”http://schemas.microsoft.com/winfx/2006/xaml/presentation”

xmlns:x=”http://schemas.microsoft.com/winfx/2006/xaml”

xmlns:my=”clr-namespace:XamlIoCDemo;assembly=XamlIoCDemo” >

<StackPanel>

<ContentControl x:Name=”barContent”>

<my:IBar />

</ContentControl>

<ContentControl Content=”{Binding Content.OtherService, ElementName=barContent}” />

</StackPanel>

</Window>

 

With IBar being an interface. I won’t go trough the details of the implementation, but here is what I wrote to parse this Xaml and display it :

IUnityContainer container = new UnityContainer();

container.RegisterType<IBar, BarImpl>();

container.RegisterType<IOtherService, OtherServiceImpl>();

 

var ctx = new WpfUnityEnabledXamlSchemaContext(container);

 

var reader = new XamlXmlReader(“SampleWindow.xaml”,ctx);

var result = System.Windows.Markup.XamlReader.Load(reader) as Window;

result.ShowDialog();

You can see that I wrote a WPF-specific xaml schema context (which is needed for the Wpf-specific features, like binding expressions). I also provided a more generic one for general purpose Xaml. I did not check it against WF 4.0, but I’ll try it in my way back from the MVP summit.