Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to remove MEF plugins at runtime?

Tags:

c#

.net

mef

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

like image 207
Márton Avatar asked Mar 22 '11 18:03

Márton


2 Answers

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.

like image 153
Wim Coenen Avatar answered Nov 10 '22 09:11

Wim Coenen


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.

like image 24
naskew Avatar answered Nov 10 '22 09:11

naskew