Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to release a shared instance from a MEF container

Tags:

c#

mef

I am trying to release a shared instance or singleton value. Does anyone know how to do this? Do I have to refresh the catalog? I'm learning MEF so please help.

Example of class

[Export]
public class Foo
{
  public RandomProperty {get;set;}

  [ImportConstructor]
  public Foo() {}
}

You can create it with something like this:

var fooSingleton = ServiceLocator.GetInstance(typeof(Foo));

All fine and good, but ideally I would like to do something like this

Container.Replace(oldFoo, newFoo);

So when I call it again

var fooSingleton = ServiceLocator.GetInstance(typeof(Foo));

fooSingleton will have the new value.

I think the answer probably relies in actually clearing out the catalog and then refreshing it - but this seem overkill for such a simple thing.

like image 674
Aim Kai Avatar asked Oct 11 '22 11:10

Aim Kai


1 Answers

By default in MEF, when you create an Export, is is shared. In many other containers, this is referred to as the Singleton lifestyle. This means that releasing the export will do nothing, since the container needs to hang on to the export for other potential consumers.

You really have 2 options in front of you:

  1. Dispose the container, assuming that you are done with it. This is appropriate when the application is shutting down for example.
  2. Change your parts to be transient objects, that is a new part is created each time you request one from the container. To do this in MEF, add a PartCreationPolicy attribute to the Export and specify it is to be non-shared. This would look like this: [PartCreationPolicy (CreationPolicy.NonShared)]. This will cause the Dispose method to be called on your parts when container.ReleaseExport(myExport) is called where myExport is an export (not an exported value) that is kept around to releasing purposes.

Here is an example:

var catalog = new AggregateCatalog(// code elided);
var container = new CompositionContainer(catalog);

Lazy<IMyExportInterface> myExport = container.GetExport<IMyExportInterface>();
// later on...
container.ReleaseExport(myExport)

This shows that you need to do this where you have access to the MEF container, and where you have kept a reference to the export.

Caution, however. Changing to transient objects instead of singletons will affect the performance of the container as reflection is used to create each new object.

like image 160
Philippe Avatar answered Oct 15 '22 10:10

Philippe