Loading and unloading PlugIns in and out of a separate AppDomain

Feb 10, 2010 at 12:24 AM

 

It seems to me that MEF does not support loading assemblies into separate appdomains.

Unless I am wrong here, the system will be of limited value unless composition and re-composition permits the loading/unloading of assemblies.

Can anyone clarify this for me?

Feb 10, 2010 at 10:32 AM
Edited Feb 10, 2010 at 10:38 AM
wszymanski wrote:

It seems to me that MEF does not support loading assemblies into separate appdomains.

Unless I am wrong here, the system will be of limited value unless composition and re-composition permits the loading/unloading of assemblies.

Can anyone clarify this for me?

Suggesting "the system will be of limited value" because it lacks the ability to unload/load assemblies in separate appdomains could be misleading to those not familiar with MEF.   After all the same could be said about Prism and Unity because they lack this capabilitiy but would be just as far from the truth as it is for MEF.  

For my purposes (http://ehr.CodePlex.com) there is nothing comparable to it and it does the job it is meant to do.   If you are looking for unloading/loading assemblies in separate appdomains you'll want to visit MAF but be prepared for a steep learning curve (pipeline).   If you don't have an application that must be up and running 24/7 the ROI will probably not be there.   I have been part of Prism projects that have had over 30 modules run without issue.   

MEF has some distinct benefits and advantages (even over Prism and Unity). 

1.  Add-in support:  years ago I attempted to provide Add-In support for the Community (Advanced) Starter Kit (CASK) so that users could simply download a module, drop it in the folder and it would appear in their admin screen where they could install/uninstall it.   This worked great and as advertised until I attempted to build a module outside of the solution (using shared assemblies).   I would get manifest errors and struggled with versioning issues (DLL hell) - I was forced to have each module have it's own set of assemblies in its own bin folder which was quickly departing from my simple download into a folder and start using it concept.   It was then I dabbled in MAF (MEF wasn't born yet) and the juice wasn't worth the squeeze.   I abandoned the concept.   The concept is alive and well with MEF and my EHR application which in time will have 24 modules compliant with government regulations for "meaningful use" that folks can pick and choose as required for site certification.

2.  Loosely coupled:  Prism/Unity require interfaces to be registered with their implementations, e.g.,  Container.RegisterType<IFoo,Foo>().   This can be done in an xml configuration easily enough but not as easy as MEF which will simply allow me to say - Import("FooContract",typeof(IFoo)) without requiring me to have a dependency on Foo - it simply needs to exist.  

3.  MEF is magical:   back in the early days Glenn Block educated me on the "Voodoo" of Unity  (I was new to DI - search for Voodoo in Unity forum).   I have been a hardcore Unity fan since and won't start my most basic application without it.   But I have found MEF to be "magical" in that it can be "BuildUp" by Unity (continuing the dependency chain).   Unity cannot BuildUp an object that has been dynamically instantiated using  Activator.CreateInstance() this has forced me to come up with work-arounds such as having foo implement an IBuildup inteface which required a method in foo that did a BuildUp(this).    The fact that MEF, in the magical way in which it dynamically creates instances, can be built up by Unity opened a big door for integrating MEF, Prism and Unity (as I have done in my EHR project).   I've been disconnected from MEF for a year or so because it is not yet released (clients are funny that way ;) but for my own project the foundation will be based on it so I get to play now.

Try building an Add-in without it and you'll quickly appreciate its raw power and simplicity.

Feb 10, 2010 at 2:36 PM

I am evaluating MEF and Unity for purposes beyond any WPF or Silverlight fron end applications. A business process, for example, needs to execute under complex business rules which are subject to frequent change. These business rules can be compiled into separate assemblies and dynamically loaded and unloaded by the business process, meaning in the world of .NET loading and unloading app domains. Restarting the business process to get the latest and greatest business rules is not an option.

I can appreciate the magic of MEF and how infatuated any of us can be with magic. But we must also remain pragmatic. So, why can MEF not be fixed to handle loading and unloading of AppDomains?

 

Feb 10, 2010 at 4:36 PM
wszymanski wrote:

So, why can MEF not be fixed to handle loading and unloading of AppDomains?

Are you sure it cannot be fixed? MEF is a very open framework and gives you access to everything under the hood. The samples in the MEF source (e.g. DynamicInstationExportProvider) and the mefcontrib project (e.g. the configurable definition provider) show that you can make your own implementations of catalogs and export providers, so I don't see why you couldn't write something like an IsolatedAppDomainCatalog and/or IsolatedAppDomainExportProvider

Please share the results if you try it. Maybe you could even contribute back to mefcontrib?

 

Feb 10, 2010 at 10:48 PM

@wszymanski, I agree whole-heartedly with everything you suggest.   I just don't think we need to throw MEF under the bus because it doesn't support it out of the box ;)    The team has done an awesome job and really delivered a quality product (for free).    I was able to easily integrate it into Prism and I trust it is extensible enough to integrate it with MAF (as suggested in the link that follows).

@wcoenen, Looks like someone may have done the leg work - http://mafmef.codeplex.com/ 

I am in the planning stages of my own project and have so much work to do, in a short period of time (goal is one year), that I have to focus on core requirements.   Wish I had the time to evaluate and play with the referenced project.   If either of you get a chance perhaps you can share the results for the community?

Feb 11, 2010 at 4:41 AM

@wcoenen is right, you could make MEF work with cross app-domain through usage of a custom programing model. You may also want to check out Kent Boogaart's blog post on using MEF and MAF together for some scenarios.  http://kentb.blogspot.com/2009/02/maf-and-mef.html

As far as why we did not do it in V1? It comes down to prioritization and  resource. It was something that people asked for, but it was low on the stack rank compared to many other features necessary to keep our partners and customers happy. Second, it is a huge undertaking, make it work seemlessly (as MEF does throughout) is a gigantic task. To do it right actually requires changes to the the CLR.

It is a problem that we are aware of, and it is on our stack of things to consider going forward.

Thanks

Glenn

Feb 15, 2010 at 3:03 PM

I have followed the suggestions provided by @wcoenen and tried solving the cross app-domain problem myself. I have looked at MAF as well as what is available at http://mafmef.codeplex.com/. MAF just does not appeal to me. So, I came up with my own solution. I would like to share it but where do I put it?

Given that it can be done via a custom solution, I am still not wholly satisfied. Firstly, the plug in component itself is bound to use MEF as a composition container and will need to 'import' references from the host. It must somehow aggregate the host's catalogs. My solution, of course, does not address this problem.

What has motivated me to look at MAF, MEF, Unity and similar frameworks is a belief that software can be developed at a much higher rate of success if it is build in smaller chunks and fitted into a framework that can transcend all isolation boundaries, app-domain, process, machine, and network. I know this is a tall order that the open source community cannot easily fill.

In the meantime, I remain torn between adapting and adoptiong open source code or developing a custom solution to achieve my immediate architectural goals.