MEF and MAF - no not the same old discussion

Nov 24, 2008 at 8:01 PM
So, To follow Microsoft speak, I'll start with the word 'so':

(skip to the bolded part if my preamble is overly verbose).

So, I've been looking at a number of alternatives for developing a composite application.  As part of this I've been taking a look at MAF,  MEF and Prism.

Originally I was looking to use MAF since it is Microsoft backed and seemed to have some nice features.  However, MAF has proven to be (IMO) very problematic in composite application scenarios.  Out of the box MAF only seems suited to fairly restrictive extensibility scenarios : particularly scenarios where AddIns do not themselves import other AddIns.  Where the usage scenario involves fairly limited extensibility contracts which are prescribed by the host application, MAF seems to work fairly well.

However, MAF falls down in composite app scenarios basically because the MAF pipeline builder tool can't correctly generate ancillary MAF classes (adapters, views etc.) for these scenarios.  Usage of MAF then breaks down under the sheer weight of having to hand code the ancillary classes required for each contract.  Uck.  Simply not practical.

So, this is where MEF comes in.  MEF is obviously targetted at exactly this kind of composite app scenario.

However, MEF doesn't seem to have taken advantage of some of the innovations introduced by MAF which could help address the composite application scenario:

MAF requires that the developer explicitly specifies the contract between the user of an AddIn and the AddIn.  MAF specifies rules governing these contracts which ensure that integration types (contract interfaces) are isolated from implementation types and that AddIns and their clients (host app) do not take direct dependencies on each other - since they only communicate with each other via contract interfaces.   The contract interfaces are deployed separately in their own assemblies.  Host and AddIn have dependencies on these contract assemblies but do not have references to each other.

What this (to me) adds up to, is that the system aids in isolating and identifying the shared binary dependencies by making them explicit.  In theory at least, when deploying an AddIn, it's assemblies could be deployed to it's own directory along with all it's assembly dependencies APART from the contract assemblies which sit in another shared directory.

Together with the use of separate AppDomain for hosted AddIns, it should usually be easy during testing to identify any deployment issues - mainly that an AddIn package (via installer or just file copy) did not include all it's binary dependencies.

My concern here is how when using MEF, AddIn development can be managed such that AddIn developers do not take dependencies on assemblies which they should not.  Assemblies which may or may not exist in subsequent versions of an application.  The problem here as I see it, is that unless AddIns are spawned in a separate AppDomain, they may deploy successfully, since dependency resolution will find and use the host app's assemblies.

Then you come to install the same AddIn on a subsequent version of the application, and ... bang.  The AddIn no longer loads due to an assembly dependency which can no longer be found - the developer of the AddIn should not have taken the dependency or should have packaged the dependent assembly along with the AddIn.

Given one of the stated aims of MEF - to allow AddIns to be used by multiple hosts this issue bears even more thought - you can easily see these kind of deployment issues occurring due to differing host apps.

So, Question:  Has Microsoft identified an approach to address this issue?  (Maybe additional technology, or at minimum a set of technical guidance).

Another related deployment issue, which I'd like to see Microsoft provide a standard pattern for, either in the API, or in guidance is handling of naming collisions:

How should naming collisions between different AddIns be handled?  I'm referring to the issue of file name collisions, particularly when AddIns are installed incrementally.

The approach I'm thinking of presently would involve the use of a distinct subdirectory for each AddIn (and AddIn version), with the subdirectory named in a pattern similar to part of the strong name for the main AddIn assembly, e.g. '[host app directory]\AddIns\PublisherCompanyName.AddInName.v1.0.0.0'.

This unfortunately is still not free of naming collision issues, particularly when using weakly named assemblies and when not hosting AddIns in a separate AppDomain.

Sorry for the long winded diatribe.  I'd greatly appreciate any guidance which can be provided.