How to remove MEF plugins at runtime?
Asked Answered
C

2

18

I have a MEF-based application that can be customized with plugins. This application has several imported parts, and I want to remove some of them at runtime (to be able to delete the .dll that contains them) when a user decides to get rid of that plugin.

CompositionBatch would do what I need, but it needs ComposablePart instances as input parameters for RemovePart() method, and I only have plain objects that implement ISomething interface, or ComposablePartDefinition instances in the AggregateCatalog. So the my question is:

  • How can I find the ComposablePart instance that represents the imported object that I want to get rid of?
  • Or alternatively: how do I get the list of ComposablePart objects that belong to a certain .dll?

I would use something like follows:

var parts = Container.Catalog.Parts
           .Where(p => iDontNeed(p))
           .Select(p => howDoIConvertComposablePartDefinition2ComposablePart(p));
var batch = new CompositionBatch();
parts.ToList().ForEach(part => batch.RemovePart(part));

Thank you

Cruikshank answered 22/3, 2011 at 18:7 Comment(0)
F
30

how do I get the list of ComposablePart objects that belong to a certain .dll?

To remove the parts from a particular assembly, you could just remove that AssemblyCatalog by calling AggregateCatalog.Catalogs.Remove. You'll have to design your parts to allow for Recomposition though.

However, this will not help you to delete the plugin assembly. The assembly will still be loaded and you cannot change or delete a .NET assembly while it is loaded. The only way to unload an assembly without stopping the process is by unloading the AppDomain in which it loaded. But if you introduce a separate AppDomain for the plugins then you'll basically have to communicate with those plugins via remoting, etcetera.

It's probably much simpler, safer and effective to just stop the application, delete the plugin assembly, and restart.

edit: actually, there is a way to delete the plugin dll file without stopping the process or unloading the entire appdomain: you can enable shadow copying for the app-domain to instruct .NET to make a copy before loading the assembly. The copy will remain loaded, but at least you can delete or replace the original file.

Fourflush answered 22/3, 2011 at 23:48 Comment(4)
Seems like it would be nice if MEF supported unloading assemblies in the future. I want to be able to update plugins in place. Restarting the application is not an acceptable compromise, and I can't overwrite the DLL without unloading the assembly. So I will probably not be able to use MEF as is. I'll have to write something with reflection.Paddlefish
@Josh G: I don't see how writing your own plugin system using reflection is going to solve anything. The described issues with unloading are not limited to MEF, this is just how .NET works.Fourflush
I'm discovering that. I assumed that I could unload an assembly with reflection as well as load it. Turns out I'm going to have to use AppDomains.Paddlefish
I recently wrote up a demo with source code on how to do this. codeproject.com/Articles/633140/…Mahler
L
1

Could MAF help you here? I am not an expert but I understand that with MAF the addins remain in their own process and can be unloaded at run time. I'd guess that this would not give the ideal performance as you are communicating cross process but if that is not a major issue it might be worth taking a look at.

Lisa answered 19/3, 2013 at 7:36 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.