Frage

When I create an object and it gets added to the container and then I'm done with it how can I ensure it's disposed of correctly?

Reading http://msdn.microsoft.com/en-us/library/ee155691(v=vs.110).aspx says

For long-lived composition containers, memory consumption by parts with a creation policy of non-shared can become a problem. These non-shared parts can be created multiple times and will not be disposed until the container itself is disposed. To deal with this, the container provides the ReleaseExport method. Calling this method on a non-shared export removes that export from the composition container and disposes it. Parts that are used only by the removed export, and so on down the tree, are also removed and disposed. In this way, resources can be reclaimed without disposing the composition container itself.

So for example if I use something like Caliburn.micro with MEF and I create a new ViewModel, when the ViewModel is closing if I add a ReleaseExport call on the container does this clean up the reference so it's no longer taking up memory? (Is this the right way to do this?)

Also does calling ReleaseExport stop me from creating another object of that type in the future, or does the catalog still contain the item and I can re-create it whenever I wish?

War es hilfreich?

Lösung

MEF allows two types of exports - shared and non-shared.

Shared exports are like singletons - every consumer shares the same instance. These shared instances are directly managed by MEF. When you call Dispose() on the MEF container, it automatically releases these objects in the reverse order of import.

Non-shared resources are more complicated. Because there are multiple instances, MEF does not guarantee a proper order of release. In this case, you should follow the same guidelines as those used for calling Dispose() to determine when to release an imported object.

Each non-shared MEF-imported object should have an owner responsible for its lifecycle - usually the parent object which imported it in the first place. Once the parent object has ensured that no one is using this imported object, it would call ReleaseExport on it. The typical pattern is to release the imported object in the Dispose() of the owner object.

class OwnerClass : IDisposable
{
    [Import(RequiredCreationPolicy=CreationPolicy.NonShared)]
    private ConsumedClass myInstance;

    [Import(RequiredCreationPolicy=CreationPolicy.Shared)]
    private CompositionContainer container;

    // Do stuff

    public void Dispose()
    {
        container.ReleaseExport(myInstance);
    {
}

Calling ReleaseExport releases that specific instance from the container. The definition remains in the catalog. So you should still be able to create more instances. Here's a nice discussion:

https://mef.codeplex.com/discussions/228535

The job of ReleaseExport is to cleanup a particular export and it's dependencies from the container early, meaning before disposing of the container itself which will cleanup and dispose all objects constructed by the container. Now calling ReleaseExport will do different things depending on the particular export, for example for a Shared export it will actually do nothing but for a NonShared export it will release it and walk its dependency graph releasing them but again it will stop and do nothing for any dependencies that are Shared exports.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top