Architecture Query for MEF based plugins

Apr 2, 2012 at 8:15 AM


I have my MEF based plugin architecture working fine except for one issue that is bugging me.

Plugins are installed (each sit) in a "Plugins" folder below the root directory where the main host application is running.  Each Plugin has it's own installation subfolder below the Plugins folder so plugin authors can install whatever they want in there without affecting others. Loading all valid plugins works fine.

Each of these plugins was compiled against a reference to the Interface (API) DLL version that was released at the time.  However and here's the BUT,  it would seem that when you attempt to load the plugins then it assumes that the referenced Interface DLL used is always the one in the host application directory and not any local version in the plugins folder.

So say I release v1 of my API DLL which has Interfaces "A", "B" and "C"  in it, each of which introduces a small set of extensions.      A plugin compiles against v1 of the API and implements "A" and "C" interfaces, and my application also uses.  Plugin loads fine and everything is dandy!

6 months later I extend the API DLL to add new interface "D" and call it v2.  Now the host application references API v2  and supports "A","B", "C" and "D" but the plugin still is compiled for v1.  Even though the plugin is not implementing Interface "D" then it refuses to load with a ReflectionTypeLoadException when MEF tryies to load via ...GetExportedValue...

So this would imply that every  time I increment the version of the API (bunch of small Interfaces as per MEF design best practice?) then any plugins compiled for the previous API wont load anymore until also recompiled.     OK I could understand that if, in the above example,  I changed  any code in "A", "B" or "C" then I'd expect it not to load, but adding a new interface (functionality) in "D" which no plugins would yet implement should not break existing plugins in my view.

Plugin authors are going to get very fed up if they have to recompile every time I extend and that seems to defeat the whole object of having an extensible architecture in MEF.

Now I could I presume not change the version number on the API DLL but that again seems then to make it impossible to validate the version of the DLL via properties in windows explorer etc so seems wrong to me as they'd all look the same aboart from bytes.

I have found from tests that I can add assembly binding redirects to the app.config file that say if v1 is requested then instead use v2 (and this does work),  but again this seems a Kludge and not a "MEF Way" of doing things?

Can anybody help/advise on the best practice/experiences for solving this as ideally I want to extend the capability (number of small interface classes) in my API DLL without breaking compiled plugins already.  Dont think that's unreasonable do you!?! 









Apr 2, 2012 at 4:17 PM

Hi Julian,

As you noted, binding redirects are applicable in this scenario. In many cases this is the best solution; each binding redirect essentially says: "as the host, I know that these two API versions are compatible, therefore allow parts built against this early API to load". Because redirects are specific, this technique will also catch any parts that depend on API versions outside of the allowed (redirected) range.

As you also mentioned, you could alternatively leave the assembly version the same between revisions of the API. Many libraries take this approach. To distinguish properly between different revisions, you can use the [AssemblyFileVersion] or [AssemblyInformationalVersion] attributes to mark the assembly with a unique identifier.

Hope this helps,