LightSwitch and the MEF story.

Hey champs!

A couple of months ago, a guy named Kostas Christodoulou opened a Q&A ticket on the Extensions Made Easy extension…

  • Written September 16, 2011
    I start a new discussion because for some strange reason I cannot reply to a discussion I started.
    My question has to do with composition. When I was looking forward to read your code (which I did) 
    I was hoping to see how one can use lightswitch and composition with his own contracts/interfaces (like IThemeExporter). 
    I have tried using my own contracts with Import/Export attributes but somehow composition seems to ignore my contracts. 
    I have ended up believing that somehow you have to "register" your contracts with MEF to achieve this, and I was expecting to see this in your solution, but I don't see anything like that. If you have any light to shed...

At the time, I couldn’t figure out what he meant so I opened a forum thread asking for more explanation (the Q&A section of an extension is really for 1 Q, several A’s, and isn’t really fit for a discussion…), but that effort turned out to be vain, and I never understood what he wanted to achieve until about 7 minutes ago, when I pushed ExtensionsMadeEasy v1.7 to the gallery…

O yea… 

Extensions Made Easy v1.7 is out!  

Will blog the changes (they are really minor) after this post…  

Wait…

This is about to become the most confusing blog post ever, but…

Extensions Made Easy v1.8 is out!

Had a really good idea after writing “v1.7 is out”, so went ahead and implemented it, published the new version, and now continuing my blogging streak of tonight…  

Now where was I… Oh yea… This fellow named Kostas asked me something about LightSwitch and MEF, which didn’t make any sense to me until about 3 hours and 7 minutes ago.  I pushed  a new version of ExtensionsMadeEasy to the gallery, which contains a bugfix that was long overdue regarding some MEF imports not being found…

What is MEF?

LightSwitch uses MEF, the Managed Extensibility Framework (which in turn is the “OldSchool” name for an open source project that got incorporated in the System.ComponentModel namespace since .NET framework 4.0, if I’m not mistaking), to glue together different subsystems at runtime.  For those of you that never heard of it, MEF uses two kinds of annotations: exports and imports.

Exports are traditionally annotations on classes that mean: “if anyone needs an instance of X (where X is a type or even a random name), create an instance of this class right here for them”.

Imports are traditionally put on fields or on a constructor (for the arguments of the constructor) which basically mean: “I need an instance of “X” here!”.

MEF is the framework that glues it all together.  You basically ask a MEF container (inversion of control) for an instance of a class, instead of calling the constructor yourself. MEF then tries to construct the object for you, and will check if the instance has any imports (for example: X, Y and Z) declared.   If it has, will try to satisfy those imports by again searching itself for exports (of for example: X, Y and Z).  For each of those exports, it will attempt to create an instance, by again checking if that instance has any imports declared, and so on…

Important note here: X (Y and Z) in the explanation above are usually types, but can even be random strings (MEF stores your types as strings anyways internally).  This means that the class that actually exports itself as being “X” and the class that imports an “X”, don’t need to know about each other (ie. be in the same or referenced assemblies).  As long as a MEF container has an export for “X”, it can satisfy all imports of “X”.

LightSwitch and MEF

The beauty of MEF is that the LightSwitch team didn’t know about your custom shell, theme, control, … extensions when they published LightSwitch.  Still, thanks to MEF, a LightSwitch application can integrate with your custom classes at runtime, because you export them under the correct names (“X”)… Vica versa, you can ask the MEF container used in your application for specific LightSwitch services and classes, beautifully disguised by something called the VSExportProviderService.

A LightSwitch application:

  • will load together different “SubSystems” at runtime into one big MEF container.  It loads:
    • all the different LightSwitch framework assemblies
    • the client projects that compose your LightSwitch application
    • the client projects from any extension that you have activated in your LightSwitch application
  • will expose this MEF container by a class called the VSExportProviderService, so that any component that requires an “X”, can simply ask for it.

The bug in EME

The bug in Extensions Made Easy, occurs when someone tried to use the EasyShell to debug his own shell extension with great ease and simplicity *cough*, and that shell has any imports declared, either directly or indirectly (by using the LightSwitch ShellHelpers and exporting an IShellViewModel).  Let’s make a quick analyses of that bug:

  • EME allows you to use a shell that is declared in a random assembly, by simply referencing the assembly and adding an EasyShellExporter to your LightSwitch client project.
  • LightSwitch, when loading the subsystems, does not add exports and/or imports from referenced assemblies to its MEF container.
  • Exports and imports have to be in the same container before MEF can do its magic.
  • No magic equals exception at runtime.

The answer… Is 42… – Good job, dear Watson.

The problem I faced when trying to fix this, is that the VSExportProviderService, only allows for components to “read from” the MEF container, but doesn’t allow components to “register” new contracts with MEF.  - Aha, when preparing this blog post, THIS was the point where after 3 months, I finally understood what Kostas ment.

The fix: “Registering” your own contracts with MEF

The fix is indeed that we will not use the VSExportProviderService itself, but hack our way into the underlying MEF container that it is using, once LightSwitch loaded all the subsystems.  The loophole can be found in the Microsoft.LightSwitch.ExportProvider.dll, containing the internally used Microsoft.VisualStudio.ExtensibilityHosting.VsCompositionContainer class.  Apparently, all you have to do to “register” your own contracts with MEF, is call one of the static Create methods on that class.

For EME, this means that when you use an EasyShellExporter, just before resolving the actual shell, I added this.

if(!(typeof(T).Assembly.Equals(this.GetType().Assembly))){
 AggregateCatalog catalog = new AggregateCatalog();
 catalog.Catalogs.Add(new AssemblyCatalog(typeof(T).Assembly));
 CompositionContainer container = new CompositionContainer(catalog);
 VsCompositionContainer.Create(container);
 }

It effectively adds the referenced assembly containing your shell to the MEF container used internally by the LightSwitch application.  (Unless you are creating your shell extension inside your LightSwitch application, in which case it will have already been loaded as a subsystem automagically…)

Big disclaimer: side effects of this technique may include but are not limited to spontaneously self-destruction of your hardware, or even worse.  Don’t hold me responsible once you start messing around as deep as this hack allows you to!

About these ads

6 thoughts on “LightSwitch and the MEF story.

  1. Pingback: Windows Azure and Cloud Computing Posts for 12/22/2011+ - Windows Azure Blog

  2. Jan, what you and Johnny are doing for the LS community is wonderful.

    It often seems like there is no Driver On Top (DOT) in .Net. There are too many separate incomplete “things” that are worked on separately by different groups.

    There needs to be a single unified architecture instead of competitive hacking between technology areas. The architecture must be stable and designed to support continuing evolution.

    Scalable RAD biz app development is the TOP priority in order to achieve full employment globally.

    Do you see XAML / LS and ASP.NET Dynamic Data converging/merging?

    http://msdn.microsoft.com/en-us/library/ee845452.aspx

    Collaborative scalable apps require using a database instead of flat files. Program code is just app data. VS is just a biz app for programmers. A biz app system rutime should be dynamic so that the instantiated app level classes required on the server and the client are based on a menu access (security) system that is responsive to the direction of the user.

    LS should be able to do both biz app forms and web sites – both with workflow, of course.

    Thoughts?

    • I Garth,
      thanks for your comment.
      I only just started thinking as LightSwitch as a MetaData driven development environment, and the advantages this offers. I have so many thoughts about this that another blog post about it must happen, I just need to get this out of my mind and “on paper”.
      Later next year, I plan to spend some time investigating the ASP.NET dynamic data integration, I see little reasons why it shouldn’t work if we can spend enough time with it, except for the SL custom controls that are so often used by SL developers… :(
      Whatever the future brings, LightSwitch (or another framework) should indeed enable us to do desktop applications, web sites and Windows Phone applications, with a uniform framework / DevEnv / architecture. It’s simply the next obvious wave in software development as we know it.
      Stay tuned for more, this is on my mind 24/7 and I’m glad to see there are people out there that think alike!

  3. I could almost cry! I found a reference to this article from http://oakleafblog.blogspot.com/ which mentioned your article and to my surprise my name was there at the top of the article. I am so glad that it finally made sense to you because I was starting to believe there were things about MEF (which is, by the way, NOT the most complex IOC library) that I was missing. My last effort in msdn forums ended up in a dispute I still haven’t managed to understand http://social.msdn.microsoft.com/Forums/en-US/lightswitchgeneral/thread/8d302b75-e105-415f-9db9-4018f8b34934
    Thanks so much for the sample. Would have any idea what is the best “place” to inject proprietary MEF contracts and catalogs? I mean in the client application the two “good looking” points would be loggedin and initialize partial methods, the earlier the better I guess. And the same question would go for the server.

    • Hey Kostas,
      I’m so glad you found your way to the post, and that you appreciated it.
      I haven’t had any time whatsoever to dive into the server side of LightSwitch, so I don’t know what the earliest point would be where you can inject your MEF catalogs… :-s
      On the client, I gutted the initialization of LightSwitch’s composition inside and out, and could not find a decent or reliable hack in it. I will explain in my next blog post (ETA 4 hours from now), so it seems the earliest one could inject this code would be in the Application_Initialize partial method…
      Happy hacking! :-)

  4. Pingback: Windows Azure and Cloud Computing Posts for 12/28/2011+ - Windows Azure Blog

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s