MEF for Windows Phone 7

by Administrator 25. June 2010 03:52

Given the momentum behind MEF at Microsoft and the fact that MEF has shipped in the box with Silverlight 4, you may find it somewhat disappointing that MEF is not available for Windows Phone 7.  Due to low level differences in the CLR for Windows Phone 7, you can’t just grab MEF from Codeplex either – read on to see the solution.

{Edit: I later posted the binaries http://www.damonpayne.com/post/2011/03/01/MEF-for-Windows-Phone-7.aspx }

The Goal

Given the Marketplace restrictions, we know that our application code must go through a QA process and be signed in order to be deployable to the Windows Phone 7 (henceforth The Phone, or WP7). It’s not surprising then that the popular Silverlight Dynamic Recomposition techniques using MEF and downloaded XAP files won’t work.  However, it’s still incredibly useful to be able to use DeploymentCatalog and friends to wire together components in an application.  Getting this scenario working on The Phone is how I’m defining success for now.

Getting MEF to Build and Run

Prior to .NET 4 and Silverlight 4 shipping MEF has been available in preview form on Codeplex.  I was surprised that, being a daily reader of Silverlightshow.net, I hadn’t already seen an article submitted by someone who had built MEF for Windows Phone 7.  Now I know why.

Trial 1 – Building MEF Preview 9 as a Silverlight 3 Project

Many Silverlight 3 assemblies will turn out to just work on The Phone.  It seems reasonable that the first thing to try is to get MEF Preview 9 from CodePlex.  You can build this as a Silverlight 3 project and then reference the binary output from a WP7 project.  Trying to use DeploymentCatalog immediately blows up at runtime though.  That would have been too easy.

Trial 2 – Referencing MEF Preview 9 as a Silverlight 3 Project with Source

Rather than just building and referencing System.ComponentModel.Composition and System.ComponentModel.Composition.Initialization as assemblies, I thought I’d add the source projects to my test solution and step through to see what was going on.  It could always be something simple and obvious.  I was getting some interesting MissingMethodException and MethodAccessException behavior so as feared this was likely going to involve source code modifications to get it working, if it was possible at all.  I moved on to the next logical choice.

Trial 3 – Building MEF as Windows Phone 7 Class Libraries

At this point I assumed some low-level binary incompatibility or missing Type was the issue so I decided to create two new WPF class library projects and add the respective MEF source files to these.  Building MEF using Windows Phone 7 Class Library as the project type would immediately show me any issues with base class library parity.   At this point I was confronted by three major issues I was previously unaware of.

No System.Reflection.Emit

I was always extremely happy that SRE was included in Silverlight, so I was a bit surprised to find it missing from The Phone.  Sure, we never had it in Compact Framework development but The Phone is a much more heterogeneous platform compared to the giant universe of Windows CE/Windows Mobile hardware.  This spells doom for some of my more advanced Silverlight development scenarios, and for certain MEF features as well.  MEF uses SRE to create dynamic implementations of interfaces for Metadata – very handy for Lazy Imports. 

I have a reasonably easy workaround for the Import Metadata issue, but eager to get my main success scenario working I commented this feature out for now and moved on.

No IQueryable

The MEF code uses a fair bit of IQueryable internally.  Not being familiar enough with LINQ Expression hacking I can’t fathom why this was left out.  Performance implications?  Required Reflection Emit?  I don’t know.  Nonetheless, this code had to be changed in places like TypeCatalog, AggregateCatalog, and the ComposablePartCatalog base class.  Until I at least got this to compile I wouldn’t know if IEnumerable would work as a surrogate for IQueryable or not.

{No IQueryable http://social.msdn.microsoft.com/Forums/en-US/windowsphone7series/thread/79858a29-4db0-460d-9a75-3630211a28fb/ }

No Dynamic Assembly Loading.  Period.

Silverlight XAP files are packaged with a Deployment Manifest that makes it easy to enumerate the assemblies included in a given XAP file.  In the Full versions of Silverlight you can use these AssemblyParts to load the assemblies and do useful things like add them to an AssemblyCatalog for MEF.

In their Zeal to prevent you from somehow loading code onto The Phone that had not gone through The Marketplace, you can’t load assemblies by name using this technique or any other technique.  Unfortunately this even includes assemblies that are hard-referenced by your WP7 Application.  What the harm would be in allowing developers to get a handle to all the assemblies that are hard-referenced is beyond me but this one is a showstopper.  Or is it?

We Can Continue, but Should We?

Suppose we can keep going.  Is MEF worthless in the Windows Phone 7 scenario given these limitations or is there still value to be had?  MEF is about Composition, Isolation, Separation, and Extensibility.  MEF is about programming against abstractions and making it easy for third parties who are unknown at compile time to extend your applications.  While some of these benefits cannot be realized given the WP7 limitations there are still meaningful benefits.

  1. Suppose you are developing frameworks and using MEF as your mechanism of wiring up Abstractions to their Implementations.  If you want to share any code with The Phone, it would suck to not at least be able to use MEF to map “IWidget to DefaultWidget”.  Programming against abstractions is always good.
  2. You may simply prefer the Import/Export programming model to alternatives like Factories and Service Locators.  Doing these things manually can take a lot of code.
  3. You may be used to ImportMany semantics, which is not a common feature in IoC containers that I know of.
  4. Microsoft may loosen up the WP7 deployment story in the future and you want to be ready.
  5. You love MEF and you have a Man-crush on  Glenn Block and you want to achieve Universal MEFness

The Current Workaround

For my part, I am working on frameworks that I’d like to recompile for Windows Phone 7, and I’ve become very accustomed to the great programming model MEF enables.  I’m NOT going to manually register every single Type I use to get around the DeploymentCatalog issues though.  Given that we can’t load assemblies by name, is there any compromise we can make?  Yes there is.

Since we can only hard-reference assemblies for Windows Phone applications, we can cheat and get a handle to each assembly we want to participate in Composition by using any Type from each assembly.  By then modifying DeploymentCatalog to add an additional constructor we can at least run some sample code and see what’s working and what’s not.  I went ahead and created a Mobile version of the Metro BBQ example I’ve been using lately.  I have an entry point application and two module assemblies and I’d like to to use MEF to glue them all together.

projects

In the entry point application there is a simple UI that displays Gas Grills and Charcoal Grills, and I’d like to create a simple ViewModel that gets populated with IGrill implementations via MEF Catalogs.

namespace MetroBBQ.Mobile
{
    public class ShellViewModel : INotifyPropertyChanged
    {
        private IEnumerable<IGrill> _AllGrills;

        [ImportMany]
        public IEnumerable<IGrill> AllGrills
        {
            get { return _AllGrills; }
            set
            {
                _AllGrills = value;
                OnPropertyChanged("AllGrills");
            }
        }              

        public event PropertyChangedEventHandler PropertyChanged;

        protected void OnPropertyChanged(string propName)
        {
            if (null != PropertyChanged)
            {
                PropertyChanged(this, new PropertyChangedEventArgs(propName));
            }
        }
        
    }
}

Now using some bootstrapper types from each assembly along with my DeploymentCatalog modifications, I create a CompositionContainer, and give it all a try.

private void PhoneApplicationPage_Loaded(object sender, RoutedEventArgs e)
{
    var shimTypes = new List<Type> { typeof(MetroBBQ.Mobile.GasGrills.Bootstrapper), typeof(MetroBBQ.Mobile.CharcoalGrills.Bootstrapper), GetType() } ;
    var deploymentCatalog = new DeploymentCatalog(shimTypes);
    var container = new CompositionContainer(deploymentCatalog);
    var vm = new ShellViewModel();
    container.ComposeParts(vm);
    DataContext = vm;
}

Sure enough, I’m now able to Compose Parts just like my MEF experience on other platforms.  There are a LOT of other scenarios to test but I’m encouraged by this initial success.  My ViewModel gets populated with IGrill implementations from two other assemblies in my Windows Phone 7 application.

GrillsScreen

 

What do you think, dear reader?  Is it worth doing more testing or shall I add this to the collection of forgotten novelties on my shelf?  Would you like the source code?  Is this worthy of MEFContrib? Leave me a comment!  For my part, I’m happy to be able to continue my MEF experience on this new platform.

Tags:

Comments (7) -

Rene Schulte
6/25/2010 10:05:26 AM #

I was wondering why you don't use the AssemblyCatalog instead of a modified DeploymentCatalog?

Something like this:

var catalog = new AssemblyCatalog(typeof(MetroBBQ.Mobile.GasGrills.Bootstrapper).Assembly);
var container = new CompositionContainer(catalog);
container.ComposeParts(this);

Reply

Damon
Damon
6/25/2010 3:52:06 PM #

I need some form of Aggregate catalog to construct the container with as I may have many assemblies (three in this example) I'd like to participate in Composition.  If I publish the code I'll create a new Catalog type for the phone.

Reply

Thomas
Thomas
6/26/2010 11:08:45 AM #

Good try!
Yes i think it could be very useful, need some test but powerful.
I'm sure it could be a part of MEFContrib Smile

Reply

Glenn Block
Glenn Block
6/28/2010 3:18:50 AM #

Nice job Damon. I for one am a big fan of getting MEF in the Phone Smile We started some conversations with the team, so hopefully we'll get somewhere. In the mean while it's nice to see the community taking advantage of MEF's license to do this. I am also glad to see someone in the community putting energy into maintaining this as I didn't have the bandwitdh to.

One recommendation is to consider providing a dummy IQueryable implementation. I did this in my own port (cid-f8b2fd72406fb218.office.live.com/.../...WP.zip) which I demoed at MIX, simply for compatability sake on the hopes that IQueryable makes it in. Smile


Reply

Rene Schulte
6/28/2010 8:48:00 AM #

Hi Damon,

there's the AggregateCatalog class.
msdn.microsoft.com/.../...ng.aggregatecatalog.aspx

It can be used like this:

var asmcatalog1 = new AssemblyCatalog(typeof(MetroBBQ.Mobile.GasGrills.Bootstrapper).Assembly);
var asmcatalog2 = new AssemblyCatalog(typeof(MetroBBQ.Mobile.CharcoalGrills.Bootstrapper).Assembly);
var catalog = new AggregateCatalog(asmcatalog1, asmcatalog2);
var container = new CompositionContainer(catalog);
container.ComposeParts(this);


BTW, nice job!

Reply

Damon
Damon
6/28/2010 5:16:33 PM #

Rene, the DeploymentCatalog functions like a specialized AggregateCatalog, so I wanted a similiar programming experience.

Reply

V.Mahadev
V.Mahadev India
4/10/2013 5:01:14 AM #

Hi Damon

Compliments
This article of yours saved lot of time and exceptionally detailed (MEF and hard referenced assemblies). Its been ages I had worked on Windows (Mobile) which dates back to PocketPC in 2001 (PocketPC). One of my blog entry on spaces had even won an PocketPC from Microsoft(MDC2004).

My View
I was experimenting to put through a framework for dynamically updating functions onto the phone application using MEF.  Although architecture defies security principles we could have used it for enterprise applications. This limitation of not allowing dynamic loading of assemblies is against to the principle commitment of the .net platform as a platform for distributed computing(dynamic building blocks - downloadable assemblies).

I tried but it fails
I downloaded your assembly created for windows7 but when referenced for windows8 throws an error message "referencing higher version and or incompatible assembly ..... not allowed"

I still need MEF for the new platform for my enterprise apps.

Thanks

Reply

Pingbacks and trackbacks (3)+

Add comment




  Country flag
biuquote
  • Comment
  • Preview
Loading


About the author

Damon Payne is a Microsoft MVP specializing in Smart Client solution architecture. 

INETA Community Speakers Program

Month List

Page List

flickr photostream