Search code examples
c#.netmef

Unable to Delete Directory after using in in an Aggregate Catalog


I am using MEF (System.ComponentModel.Composition) CompositionContainer, in Visual Studio 2017, with .net 4.5.1, to load some classes from a dll from a directory X.

_catalogs = new AggregateCatalog();
var dir = new DirectoryCatalog("X", "*.dll");
compositionContainer = new CompositionContainer(_catalogs, true);
compositionContainer.ComposeParts();

I am able to access what I need without problems. At some point, I am removing the directory from the composition:

 _catalogs.Catalogs.Remove(_catalogs.Catalogs.First());

This works, and after that, I have no instance of my dll in the CompositionContainer or the AggregateCatalog.

My problems it that now, if my application is still opened, I cannot delete the directory "X", or move it or rename it. I get an 'Access to path is denied' message, from code or from Explorer.

Anyone know what could cause the directory to still be attached to the CompositionContainer even after it is removed? Or am I removing it wrong?

Thank you.


Solution

  • Pfff... It is not enough with removing the catalog or even calling Dispose() on it. Why? Because MEF by default loads your catalog's assemblies into the current AppDomain. That means that your assemblies files are blocked by your AppDomain, that is why you can not perform any IO operation on them.

    From documentation about loading and unloading assemblies:

    There is no way to unload an individual assembly without unloading all of the application domains that contain it. Use the Unload method from AppDomain to unload the application domains. For more information, see How to: Unload an Application Domain.

    Now, obviously you can not unload your AppDomain because you only have one =). So, that let us with only one alternative, yes, you are right: use another AppDomain

    I had the very same requirement a couple of months ago and I followed along this CodeProject article, that helped me a lot. The article's name is MEF and AppDomain - Remove Assemblies On The Fly, which is pretty much what you need =)

    EDIT The OP solved this issue with the default appDomain setting ShadowCopyFiles on:

    AppDomain.CurrentDomain.SetShadowCopyFiles();