How to release a shared instance from a MEF container
I am trying to release a shared instance or singleton value. Does anyone know how to do this? Do I have to refresh the cata开发者_StackOverflowlog? 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.
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:
- Dispose the container, assuming that you are done with it. This is appropriate when the application is shutting down for example.
- 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 theDispose
method to be called on your parts whencontainer.ReleaseExport(myExport)
is called wheremyExport
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.
Because you are using a Shared
creation policy, the container will keep a reference to the part created. What you can do to release the part is grab the containing export from the container, and release.
var export = container.GetExport<Foo>();
container.ReleaseExport(export);
You'll likely need to update your consuming type (where your Import
s are), to support recomposition.
精彩评论