thinking about MEF as another IoC container led us into misconception.
MEF design goal was being a generic extensibility infrastructure,
its just happens that it overlap with the IoC world (and yes it has most of the IoC feature).
this post address the challenge of building extensions over none CLR types (like image files)
from the technical perspective it will discuss the following techniques:
- Building Export Providers
- Design recomposable extensions
- Creating DataSourceProvider (which will used for WPF binding)
the source code for this post can be found here.
Our Test Case
in order to demonstrate the above techniques I choose common scenario of building
very simple WPF application that display pictures which came from heterogeneous data source providers.
The Solution Modeling
this components design by the MEF team as centric handle for the MEF container functionality
(i did very minor changes to the CompositionHost class, basically exposing the underline container as Export Provider)
this is the heart of this post,.
Export providers (not the catalog) is the underline MEF unit that responsible for the instantiation of the exported parts.
the different providers implementations (local, Picasa, Fickr) has the knowledge of
how to instantiate the discovered photo files into CLR type that implement IPhotoInfo.
this class is responsible for abstracting the WPF application from it actual photos sources.
is the UI implementation
from this point i will start to explain the different techniques used in the application,
starting with the UI.
UI (WpfImageViewerUI project)
At the code behind level, it initial the Container with custom MEF Export Providers
and pass the container to the Composition Host (the composition host used as
the default container, it is reachable from anywhere in the code)
At the Xaml level we embed the Style.xaml
For better separation between the graphical designer and the developer, I’m using the style.xaml
as the designer own xaml (only the designer should touch this file, he can change styles and templates).
this is the developer own xaml, which the designer shouldn’t touch.
it should contain the minimal xaml needed, from the functionality perspective
(it should not have any beauty factor actually it should be really ugly without the style.xaml)
as you can see it kept short, clean and easy to understand.
from the debugging perspective you can disembed the style.xaml and check whether the
bug came from the functionality or the design.
this xaml contain:
MEFPhotoDataSourceProvider (which is the binding source of the list’s ItemSource)
UI.Components (define the MEFPhotoDataSourceProvider class)
as we mention earlier we using data source provider to abstract the actual origin of the data.
the xaml won’t have to be changed whenever adding or removing data sources.
another benefit is the ability of a-sync loading (data source that expose hundreds of photos cannot expose synchronously)
at line 15, you can see that we using the ImportMany decoration with AllowRecomposition = true
this is the key of the a-sync capabilities (lazy loading).
you can download the source code from here and run the application with and without AllowRecomposition
in order to see its effect.
at line 20, PartInitializer.SatisfyImports(this) is actually asking the default MEF container (which we define at the app.xaml)
for the discovered export parts that match the import.
at line 22, we introduce the base class with our data source collection.
at the constructor level line 7, CompositionHost.Host.ExportsChanged += OnPhotosChangedHandler we register to the
default MEF container changed event (again the a-sync lazy loading)
at the OnPhotosChangedHandler, line 25, we adding any new composed instances into the bind-able collection.
Finally we got into the heart of extensibility model, the Export Providers
we use custom Export Provider for discovering none CLR entities (in our case photo files) and introduce it to the CLR world
via the MEF infrastructure as instances that implement IPhotoInfo.
the ImageExportProviders project contain 4 files (one base class and 3 providers)
ImageExportProviderBase is the provider base class
The GetExportsCore is what we have to override when creating custom Export Provider.
you can see at line 12, that we check whether the import definition is recomposable and act accordingly.
in case of recomposable the IntroduceNewExport method is where we notify about the new available exports.
the 3 derived class is just a parser for specific source type.
LocalImageExportProvider discover and parse file on the local file system.
FlickrImageExportProvider discover and parse file from the Flickr web site.
Flickr API does not support thumbnails, which results that pictures discovered on Flickr will appear with delay.
PicasaImageExportProvider discover and parse file from the Picasa web site.
the MEF ability to compose beyond the CLR world is one of its underline extensibility design that
differentiate MEF from typical IoC containers.
and we can use MEF to abstract our data sources achieving a-sync and loosely coupled advantage.
the source code for this post can be found here.